這是我參與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/\