在处理一个矩阵 matrix[][] 时,虽然很清楚接下来该怎么做,但最后的结果往往会报数组越界的错误,致使编程5分钟,排错2小时,极其浪费时间。
究其原因,是没有理清矩阵与二维数组的对应关系,甚至与坐标轴混淆,且听我一点一点分析。
首先,我们需要创建一个二维数组 arr 来存储一个m*n的矩阵 matrix,有多种方法可以参考前文 Javascript的一些坑点,这里使用es6的简介写法
let arr = new Array(m).fill(0).map(v => new Array(n).fill(0));
matrix 与 arr 的第一个对应关系:
matix为m行n列的矩阵:则
arr.length === m
arr[0].length === n
这个很好理解
然后,我们可以用 arr[x][y] 保存当前矩阵的元素,但是这样做极其容易出错,出错的原因是会与坐标轴的混淆
arr[x][y] 在矩阵上 是 第x行第y列的元素,在坐标轴上 是 (y, x)
且
x的范围为 0<=x<n
y的范围为 0<=y<m
因此在实际编程中,受坐标系的影响往往会写出以下代码,导致数组越界:
while(x>=0 || x<列数 || y>=0 || y<行数)
所以,如果你如果实在摆脱不了坐标轴的影响,你可以这样定义遍历中的矩阵元素:arr[y][x] 上述问题即可解决,只不过写起来读起来会比较变扭
总结下写法,定义 x,y 分别为 arr 的 行号,列号,则
0<=x<arr.length
0<=y<arr[0].length
使用元素便能直接用 arr[x][y] 了
let arr = matrix;
let m = matix.length, n = matrix[0].length;
let x = 0, y = 0;
while(x>=0 || x<n || y>=0 || y<m) {
arr[x][y]
}
这样写就一点问题就没了
拿一道BFS的题来验证下:
/**
* @param {character[][]} maze
* @param {number[]} entrance
* @return {number}
*/
/**
* @param {character[][]} maze
* @param {number[]} entrance
* @return {number}
*/
var nearestExit = function(maze, entrance) {
let [U, L, D, R] = [ [-1,0], [0,-1], [1,0], [0,1] ];
let queue = [];
let m = maze.length, n = maze[0].length;
queue.unshift(entrance);
maze[entrance[0]][entrance[1]] = '+';
let res = 0;
while(queue.length !== 0) {
let tmp = [];
res++;
while(queue.length !== 0) {
let [x0, y0] = queue.pop();
for(let [dx, dy] of [U, L, D, R]) {
let x = x0+dx;
let y = y0+dy;
if(x<0 || x>m-1 || y<0 || y>n-1) continue;
if(maze[x][y] === ".") {
if(x===0 || x===m-1 || y===0 || y===n-1) return res;
else {
maze[x][y] = '+';
tmp.unshift([x,y]);
}
}
}
}
queue = tmp;
}
return -1;
};