引言
今天刷力扣题目偶遇0-1背包问题,在创建二维数组上面踩了坑,写一篇文章来记录一下。
创建
自己踩的坑
例如我要动态创建一个5x5的二维数组,我的创建方法是
var arr = new Array(5).fill(new Array(5).fill(0))
如下图所示确实创建了一个5x5的二维数组:
如果想要对
arr[0][0]
进行赋值操作,那么会出现下面的情况
会发现整一列的值都被修改成1了。
那么二维数组应该怎么动态创建呢?
按照定义封装函数
二维数组其实就是从每一个一维数组再创建一个一维数组,那么可以封装一个函数,代码如下:
function twoDimArr(m,n){
let a = new Array();
for(let i=0;i<m;i++){ //一维长度为m
a[i] = new Array();
for(let j=0;j<n;j++){ //二维长度为n
a[i][j] = 0;
}
}
return a;
}
检查一下对arr[0][0]
赋值,发现没有问题
优化代码
对封装的代码进行优化
使用fill()方法
arr.fill(value, start, end) —— 从索引 start 到 end ,用重复的 value 填充数组,start和end是可选项,如果不写就是整个数组。 优化后的代码如下:
function twoDimArr(m,n){
let a = new Array();
for(let i=0;i<m;i++){ //一维长度为m
a[i]=new Array(n).fill(0);
}
return a;
}
那么有没有可能一行代码就搞定呢,毕竟在其他语言中创建二维数组并不需要这么复杂。
使用Array.prototype.map()方法
map(func) —— 根据对每个元素调用 func 的结果创建一个新数组。 它对数组的每个元素都调用函数,并返回结果数组。
let result = arr.map(function(item, index, array) {
// 返回新值而不是当前元素
})
例如
const array1 = [1, 4, 9, 16];
// pass a function to map
const map1 = array1.map(x => x * 2);
console.log(map1);
// expected output: Array [2, 8, 18, 32]
最终的优化代码如下所示:
function twoDimArr(m,n){
let arr=new Array(m).fill(1).map(()=>new Array(n).fill(0));
return arr;
}
当然了,第一个fill函数内部填什么都无所谓,因为它里面的内容会被第二个fill、 覆盖掉。
排序
再来谈一谈对二维数组进行排序。 首先回顾一下数组内置的排序方法sort
sort(fn)
对数组进行 原位(in-place) 排序,更改元素的顺序。默认排序顺序是在将元素转换为字符串,然后比较它们的UTF-16代码单元值序列时构建的
arr.sort([compareFunction])
如果没有指明 compareFunction ,那么元素会按照转换为的字符串的诸个字符的Unicode位点进行排序。如果指明了 compareFunction ,那么数组会按照调用该函数的返回值排序。即 a 和 b 是两个将要被比较的元素:
- 如果 compareFunction(a, b) 返回值小于 0 ,那么 a 会被排列到 b 之前;
- 如果 compareFunction(a, b) 返回值等于 0 , a 和 b 的相对位置不变。备注: ECMAScript 标准并不保证这一行为,而且也不是所有浏览器都会遵守(例如 Mozilla 在 2003 年之前的版本);
- 如果 compareFunction(a, b) 返回值大于 0 , b 会被排列到 a 之前。
对于一维数组升序排序可以这么写:
let arr=[ 12,4,6,8,19,22];
arr=arr.sort((a,b)=>{
return a-b;
});
console.log(arr);//[ 4, 6, 8, 12, 19, 22 ]
那么对于二维数组怎么排序呢?
如上图所示,对二维数组可以按照列进行排序。上面我们说明了,二维数组可以看成是一维数组又创建了一个一维数组,我们调用sort方法时,a和b就相当于是二维数组中的第一维,就是所有横着的项。那么a[1]
就相当于arr[i][1]
,就是第一列,那么对二维数组第n列排序就可以写成:
arr=arr.sort((a,b)=>{
return a[n]-b[n];
})