算法随笔-数据结构(数组)

181 阅读7分钟

算法随笔-数据结构(数组)

本文主要介绍数组的定义、访问元素的方法、属性和各种数组方法:搜索、比较、添加、删除、截取、转换、修改等,题解 leetCode 真题。供自己以后查漏补缺,也欢迎同道朋友交流学习。

引言

之前写了几篇关于队列链表哈希相关的文章,回过头发现最最基础的字符串数组忘记写了。

数组是代码中最常用的数据结构了,只要是有列表的地方都是以数组形式去表现的。对数组的属性和方法我们也非常熟悉,但有一些方法其实还是不怎么了解的.

今天我就整理下把数组相关的方法都简单介绍下,并做俩道关于数组的 leetCode 题。

基本概念

数组是一种常用的数据结构,用于存储一系列相关数据。在 JS 中,数组是一种特殊的对象类型,它可以存储任意类型的数据,包括其他数组、对象等。

数组中的每个元素都有一个唯一的索引,索引通常是基于的整数(即从0开始)。

数组定义

数组可以通过字面量和构造函数的方式创建,一般常用字面量方式。

// 字面量定义
var arr = [1, 2, 3];
// 构造函数定义
var arr = new Array(1, 2, 3)

访问数组元素

数组可以通过下标访问元素,默认从 0 开始。

var arr = [1, 2, 3];
// 访问数组元素
console.log(arr[0]); // 1
console.log(arr[2]); // 3

数组的属性和方法

数组有非常多的属性和方法,用于判断、搜索、改变数组。

属性类

数组的属性,可以直接获取到。

length

获取或设置数组的长度。

let arr = [1, 2, 3];
console.log(arr.length); // 输出: 3
arr.length = 2;
console.log(arr); // 输出: [1, 2]

查找类

indexOf(searchElement[, fromIndex])

返回数组中第一次出现的指定元素的索引。

let arr = [1, 2, 3, 2, 4];
let index = arr.indexOf(2);
console.log(index); // 输出: 1
lastIndexOf(searchElement[, fromIndex])

返回数组中最后一次出现的指定元素的索引。

let arr = [1, 2, 3, 2, 4];
let index = arr.lastIndexOf(2);
console.log(index); // 输出: 3
forEach(callbackFn[, thisArg])

对数组中的每个元素执行一次提供的函数。

let arr = [1, 2, 3];
arr.forEach((value, index, array) => {
  console.log(value, index, array);
});
// 输出:
// 1 0 [1, 2, 3]
// 2 1 [1, 2, 3]
// 3 2 [1, 2, 3]
entries()

返回一个迭代器对象,键值对为数组的索引和值。

let arr = [1, 2, 3];
let iterator = arr.entries();
console.log(iterator.next().value); // 输出: [0, 1]
console.log(iterator.next().value); // 输出: [1, 2]
console.log(iterator.next().value); // 输出: [2, 3]
keys()

返回一个迭代器对象,键为数组的索引。

let arr = [1, 2, 3];
let iterator = arr.keys();
console.log(iterator.next().value); // 输出: 0
console.log(iterator.next().value); // 输出: 1
console.log(iterator.next().value); // 输出: 2
values()

返回一个迭代器对象,值为数组的元素。

let arr = [1, 2, 3];
let iterator = arr.values();
console.log(iterator.next().value); // 输出: 1
console.log(iterator.next().value); // 输出: 2
console.log(iterator.next().value); // 输出: 3

比较判断类

includes(searchElement[, fromIndex])

检查数组是否包含指定的元素。

let arr = [1, 2, 3, 2, 4];
let found = arr.includes(2);
console.log(found); // 输出: true
every(callbackFn[, thisArg])

检查数组中的所有元素是否都满足条件。

let arr = [1, 2, 3];
let result = arr.every(x => x > 0);
console.log(result); // 输出: true
some(callbackFn[, thisArg])

检查数组中是否有任何元素满足条件。

let arr = [1, 2, 3];
let result = arr.some(x => x > 2);
console.log(result); // 输出: true

拼接/转换类

push(element1[, element2[, ...]])

在数组的末尾添加一个或多个元素,并返回新的长度。

let arr = [1, 2, 3];
let len = arr.push(4);
console.log(len); // 输出: 4
console.log(arr); // 输出: [1, 2, 3, 4]
pop()

移除数组的最后一个元素,并返回该元素的值。

let arr = [1, 2, 3];
let lastElement = arr.pop();
console.log(lastElement); // 输出: 3
console.log(arr); // 输出: [1, 2]
shift()

移除数组的第一个元素,并返回该元素的值。

let arr = [1, 2, 3];
let firstElement = arr.shift();
console.log(firstElement); // 输出: 1
console.log(arr); // 输出: [2, 3]
unshift(element1[, element2[, ...]])

在数组的开头添加一个或多个元素,并返回新的长度。

let arr = [1, 2, 3];
let len = arr.unshift(0);
console.log(len); // 输出: 4
console.log(arr); // 输出: [0, 1, 2, 3]
concat(array1[, array2[, ...]])

连接两个或多个数组,并返回一个新的数组。

let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
let concatenated = arr1.concat(arr2);
console.log(concatenated); // 输出: [1, 2, 3, 4, 5, 6]
reverse()

反转数组元素的顺序。

let arr = [1, 2, 3, 4, 5];
arr.reverse();
console.log(arr); // 输出: [5, 4, 3, 2, 1]
sort(compareFunction)

对数组元素进行排序,默认按照字符串的 Unicode 字典顺序排序。

let arr = [1, 10, 2, 21, 3];
arr.sort();
console.log(arr); // 输出: [1, 10, 2, 21, 3]

// 使用自定义排序函数
arr.sort((a, b) => a - b);
console.log(arr); // 输出: [1, 2, 3, 10, 21]
join(separator)

将数组的所有元素连接成一个字符串。

let arr = [1, 2, 3];
let joined = arr.join('-');
console.log(joined); // 输出: 1-2-3
toString()

将数组转换为字符串,等同于 join()

let arr = [1, 2, 3];
let str = arr.toString();
console.log(str); // 输出: 1,2,3
toLocaleString()

返回一个本地化的字符串表示。

let arr = [1, 2, 3];
let localeStr = arr.toLocaleString();
console.log(localeStr); // 输出: 1,2,3
filter(callbackFn[, thisArg])

创建一个新数组,其包含通过测试的所有元素。

let arr = [1, 2, 3, 4, 5];
let filtered = arr.filter(x => x > 2);
console.log(filtered); // 输出: [3, 4, 5]
map(callbackFn[, thisArg])

创建一个新数组,其结果是该数组中的每个元素都调用一个函数处理过。

let arr = [1, 2, 3];
let mapped = arr.map(x => x * 2);
console.log(mapped); // 输出: [2, 4, 6]
reduce(callbackFn[, initialValue])

对数组中的每个元素执行一个由您提供的“reducer”函数,将其结果汇总为单个输出值。

let arr = [1, 2, 3, 4];
let sum = arr.reduce((accumulator, currentValue) => accumulator + currentValue);
console.log(sum); // 输出: 10
reduceRight(callbackFn[, initialValue])

从右到左执行 reduce 函数。

let arr = [1, 2, 3, 4];
let product = arr.reduceRight((accumulator, currentValue) => accumulator * currentValue);
console.log(product); // 输出: 24
flat(depth)

将数组扁平化到一定的深度。

let arr = [1, [2, [3, [4]]]];
let flattened = arr.flat(2);
console.log(flattened); // 输出: [1, 2, 3, [4]]
flatMap(callback[, thisArg])

首先对数组中的每个元素调用一个映射函数,然后将结果扁平化一级,返回一个新数组。

let arr = [1, 2, 3];
let flatMapped = arr.flatMap(x => [x, x * 2]);
console.log(flatMapped); // 输出: [1, 2, 2, 4, 3, 6]

截取类

slice(start[, end])

返回数组的一部分浅拷贝,不会修改原数组。

let arr = [1, 2, 3, 4, 5];
let sliced = arr.slice(1, 3);
console.log(arr); // 输出: [1, 2, 3, 4, 5];
console.log(sliced); // 输出: [2, 3]
splice(start[, deleteCount[, item1[, item2[, ...]]]])

用于添加/删除项目,返回被删除的项。

let arr = [1, 2, 3, 4, 5];
let removed = arr.splice(1, 2, 'a', 'b');
console.log(arr); // 输出: [1, 'a', 'b', 4, 5]
console.log(removed); // 输出: [2, 3]

leetCode 真题

118. 杨辉三角

给定一个非负整数 numRows,生成「杨辉三角」的前 numRows 行。

在「杨辉三角」中,每个数是它左上方和右上方的数的和。

杨辉三角

示例1

输入:numRows = 5

输出:[[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]

示例2

输入:numRows = 1

输出:[[1]]

题解

思路:双循环去新建数组,默认每一行的第一个和最后一个元素都是 1,后面中间值累加就取当前的左上方和右上方的数。

/**
 * @param {number} numRows
 * @return {number[][]}
 */
var generate = function(numRows) {
  let res = []
  for (let i = 0; i < numRows; i++) {
    // 每一行新建空数组
    res[i] = [];
    // 每一行的第一个和最后一个都是1
    res[i][0] = res[i][i] = 1;
    // 从第二行比较
    for (let j = 1; j < i; j++) {
      // 左上方的数 + 正上方的数
      res[i][j] = res[i - 1][j - 1] + res[i - 1][j];
    }
  }
  return res;
};

53. 最大子数组和

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大

子数组是数组中的一个连续部分。

示例1

输入:nums = [-2,1,-3,4,-1,2,1,-5,4]

输出:6

解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。

示例2

输入:nums = [1]

输出:1

示例3

输入:nums = [5,4,-1,7,8]

输出:23

题解

思路:利用动态规划,首先对数组进行遍历,当前最大连续子序列和为 sum,结果为 total

循环的去比较累加值是否大于 0,大于 0 则继续累加,不然则把当前的 sum 赋值为当前遍历值,

最后比较 totalsum 那个值大,就把值赋给 total

/**
 * @param {number[]} nums
 * @return {number}
 */
var maxSubArray = function(nums) {
  let total = nums[0];
  let sum = 0;
  // 循环遍历
  for (let i = 0; i < nums.length; i++) {
    // 累加值大于 0,则继续累计
    if (sum > 0) {
      sum += nums[i];
    } else {
      // 否则把当前值赋给sum
      sum = nums[i];
    }
    // 比较最大值
    total = Math.max(total, sum);
  }

  return total;
};