代码随想录算法训练营 | 数组理论基础

一. 一维数组

数组是存放在连续内存空间上的相同类型数据的集合。
数组的元素无法删除,只能覆盖。

1.1 创建数组

const arr1 = [1,2,3,4,5];
const arr2 = Array(5).fill(0);// 新建数组[0,0,0,0,0]
const arr3 = new Array(5).fill(0);// 新建数组[0,0,0,0,0]
const arr4 = Array(5).fill(0).map(idx => idx + 1); // 新建数组[1,2,3,4,5]
const arr5 = new Array(1,2,3,4,5); // 新建数组[1,2,3,4,5]

1.2 遍历数组

  1. for循环
const arr = ['a','b','c'];
for(let idx = 0; idx < arr.length; idx ++) {
    const item = arr[idx];
    ...
}
  1. forEach循环
arr.forEach((item, idx) => {
	...
});
  1. for…of遍历(ES6)
for (let item of arr) {
    ...
}

for (let [idx, item] of arr.entries()) {
    ...
}
// arr.entries()等于Array Iterator [[0, 'a'], [1, 'b'], [2, 'c']]

注意:
遍历数组不要用for…in。因为for…in会遍历对象的所有可枚举属性,包括其原型链中的属性。

1.3 识别数组

参考:https://www.cnblogs.com/echolun/p/10287616.html

  1. Array.isArray
Array.isArray(arr) // true
  1. instanceof运算符
    instanceof 运算符用于检查对象的原型链中是否包含指定构造函数的 prototype 属性。
    arr instanceof Array 为例,该表达式会验证 arr 是否由 Array构造函数创建(即 Array.prototype 是否在其原型链上),若成立则返回 true
arr instanceof Array // true
  1. constructor属性
    JavaScript 中,对象的 constructor 属性默认指向创建该实例的构造函数。因此,只有当数组 arr 是通过原生 Array 构造函数(而非子类或其他方式)生成时,以下表达式才成立:
arr.constructor === Array; // true
  1. Object.prototype.toString().call()
    表达式Object.prototype.toString.call(a) 通过调用原生 toString 方法返回格式化的类型字符串。
Object.prototype.toString.call([]) // "[object Array]"
Object.prototype.toString.call(function(){}) // "[object Function]" 
Object.prototype.toString.call(123) // "[object Number]"

注意:
数组和对象的type都是’object’,不能用typeof判断是否是数组。

typeof [] === 'object' // true
typeof {} === 'object' // true

1.4 拷贝数组

见:浅拷贝或深拷贝js数组或对象的方法

1.5 Array常用方法

见:Array数组常用方法总结(javascript版)

二. 二维数组

二维数组的每个元素是一个一维数组。
C++中,数组是提前规定了所有元素的类型和大小的,数组是存在内存中的一段连续的内存地址中的,且二维数组中的arr[0][0]、arr[0][1]…到arr[m][n]也是存在一段连续内存地址中的。假如要找arr[x],可以直接根据首项地址和元素大小算出来。
而JavaScript中,数组是一个对象,索引的对象的键值,同时数组是动态的,可以包含任何类型任何大小的元素,所以js数组是以类似链表的方式存储的,每个项都存储了下一个项的引用,而不是计算下一个项的内存地址。假如要找arr[x],需要从首项开始一路找过去。

2.1 创建二维数组

const arr1 = [
    [1,0],
    [1,1],
    [1,2],
];

const arr2 = Array(3).fill(0).map((item, idx) => [1, idx]); // 新建数组[[1,0],[1,1],[1,2]]

const arr3 = new Array(3).fill(0);
arr3.forEach((item, idx) => {
    arr3[idx] = [1,idx];
});
// 或
for (const i = 0; i < arr3.length; i ++) {
    arr3[i] = [1,i];
}

为什么arr1和arr3中还要先fill再map和forEach?因为Array(5)建出来的是数组长度为3的空槽,map和forEach不访问空槽。
为什么不直接Array(3).fill([1, 0]).map((item, idx) => item[1] = idx)?因为fill传入对象的话,会导致被填充的数组每个元素都引用这个对象,之后只要改一个元素,整个数组就全都会变。

2.2 遍历二维数组

双重for循环

2.3 查找二维数组

function search(value) {
    for (let i = 0; i < matrix.length; i++) {
        for (let j = 0; j < matrix[i].length; j++) {
            if (matrix[i][j] === value) {
                return {found: true, row: i, col: j};
            }
        }
    }
    return { found: false };
}

2.4 转置二维数组

前提是二维数组的行数与列数相等。
let transposed = matrix[0].map((col, i) => matrix.map(row => row[i]));

本文参考:https://programmercarl.com/数组理论基础.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值