这是我参与8月更文挑战的第9天,活动详情查看:8月更文挑战数组
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每个数字。markdown
分析:矩阵能够用二维数组来模拟。oop
示例 :post
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]
复制代码
关键点:在四个拐角处改变方向。spa
模拟打印矩阵的路径:初始位置是矩阵的左上角,初始方向是向右,当路径超出界限或者进入以前访问过的位置时,顺时针旋转,进入下一个方向。code
判断路径是否进入以前访问过的位置须要使用一个与输入矩阵大小相同的辅助矩阵visited,其中的每一个元素表示该位置是否被访问过。当一个元素被访问时,将 visited 中的对应位置的元素设为已访问。orm
判断路径是否结束:当路径的长度 等于 矩阵中的元素数量时即为完整路径,将该路径返回。leetcode
var spiralOrder = function(matrix) {
if (!matrix.length || !matrix[0].length) {
return [];
}
// rows和columns是边界,总数是total,
var rows = matrix.length, columns = matrix[0].length;
var total = rows * columns;
// 定义一个辅助数组,初始值都为false,判断某个位置是否赋值过
let varArr = new Array(rows).fill(0).map (() => new Array(columns).fill(false))
// 定义一个初始值是0的一维数组
var order = new Array(total).fill(0)
// 定义 变量 row column nextRow nextColumn dirIndex
var row=0, column=0, dirIndex = 0;
// 定义一个用来拐弯的数组
let direction = [ [0,1], [1,0],[0,-1], [-1,0] ]
for( let i=0; i< total; i++ ) {
// 把当前定位到的值取出放入结果数组中
order[i] = matrix[row][column]
varArr[row][column] = true
const nextRow = row + direction[dirIndex][0]
const nextColumn = column + direction[dirIndex][1]
if( !( 0 <= nextRow && nextRow < rows && 0 <= nextColumn && nextColumn < columns && !(varArr[nextRow][nextColumn]) )){
dirIndex = (dirIndex+1) % 4
}
row += direction[dirIndex][0]
column += direction[dirIndex][1]
}
return order;
};
复制代码
代码分析:get
能够将矩阵当作若干层,首先打印最外层的元素,其次打印次外层的元素,直到打印最内层的元素。it
对于每层,从左上方开始以顺时针的顺序遍历全部元素。假设当前层的左上角位于 (top,left),右下角位于 (bottom,right),按照以下顺序遍历当前层的元素。
从左到右遍历上侧元素,依次为 (top,left) 到 (top,right)。
从上到下遍历右侧元素,依次为 (top+1,right) 到(bottom,right)。
若是 left<right 且 top<bottom,则从右到左遍历下侧元素,依次为(bottom,right−1) 到 (bottom,left+1),以及从下到上遍历左侧元素,依次为 (bottom,left) 到 (top+1,left)。
遍历完当前层的元素以后,将 left 和 top 分别增长 1,将 right 和 bottom 分别减小 1,进入下一层继续遍历,直到遍历完全部元素为止。
var spiralOrder = function(matrix) {
if (!matrix.length || !matrix[0].length) {
return [];
}
const rows = matrix.length, columns = matrix[0].length;
const order = [];
let left = 0, right = columns - 1, top = 0, bottom = rows - 1;
while (left <= right && top <= bottom) {
for (let column = left; column <= right; column++) {
order.push(matrix[top][column]);
}
for (let row = top + 1; row <= bottom; row++) {
order.push(matrix[row][right]);
}
if (left < right && top < bottom) {
for (let column = right - 1; column > left; column--) {
order.push(matrix[bottom][column]);
}
for (let row = bottom; row > top; row--) {
order.push(matrix[row][left]);
}
}
[left, right, top, bottom] = [left + 1, right - 1, top + 1, bottom - 1];
}
return order;
};
复制代码
代码分析:
这种方法比较好理解,就是每一层四个方向走完,以后将 left 和 top 分别增长 1,将 right 和 bottom 分别减小 1,进入下一层继续走,直到走完全部元素为止。
var spiralOrder = function(matrix) {
const res = []
let flag = true
while(matrix.length) {
// 从左到右
if(flag){
// 第一层
res = res.concat(matrix.shift())
// '如今'的第一层到最后一层的末尾
for(let i=0; i<matrix.length; i++){
matrix[i].length && res.push(matrix[i].pop())
}
// 右到左
} else {
// 最后一层
res = res.concat(matrix.pop().reverse())
// '如今'的最后一层到第一层
for(let i=matrix.length - 1; i>= 0; i--){
matrix[i].length && res.push(matrix[i].shift())
}
}
flag = !flag
}
return res
};
复制代码
代码分析:
这段代码每遍历一个数都是在原数组中直接删除这个数。拿一个4*3的二维数组举例:
[[1,2,3,4],[5,6,7,8],[9,10,11,12]]
首先,先遍历最上面的一行[1,2,3,4],并在原数组中删除这一行,如今原数组变成了:[[5,6,7,8],[9,10,11,12]];而后遍历垂直的左右边的一列8和12,如今原数组变成了:[[5,6,7],[9,10,11]];接着,弹出原数组最下面一层[9,10,11]并反转为[11,10,9],如今原数组变成了:[[5,6,7]];而后从头一个一个弹出最后一层的五、六、7;
连接:leetcode-cn.com/\