一、求解方法?
(1)按點模擬路徑
? ? ? ? 在原有坐標的基準上,疊加 橫縱坐標 的變化值,求出下一位置,并按題完成要求。但需注意轉角的時機判斷,特別是最后即將返回上一出發點的位置。
(2)按層模擬路徑
? ? ? ? 在原有的形狀基礎上,畫出 上下左右 四根邊界線,按照順序完成畫圈。但需要關注單行或單列可能存在重復的情況,因此需在操作?下 和 左 邊界線時加上判定條件。
(3)心路歷程
? ? ? ? 最開始掌握的是 Carl 教的循環畫框類的思路,但是它的應用是在方形樣式,其中的 offset 和 中間元素處理對于方形圖案比較好處理,但是針對矩形樣式,我真的不知道要怎么改了。后改學其他思路,也就是上述兩種。
二、推薦例題
(1)方形樣式的螺旋矩陣
????????59. 螺旋矩陣 II
方法1:點模擬
class Solution {public int[][] generateMatrix(int n) { int curNum = 1;int maxNum = n * n;int curRow = 0;int curCol = 0;int dirIndex = 0;int[][] dirs = {{0,1}, {1,0}, {0,-1}, {-1,0}};int[][] res = new int[n][n];while(curNum <= maxNum){res[curRow][curCol] = curNum++;//判定后續位置是否越界int nextRow = curRow + dirs[dirIndex][0];int nextCol = curCol + dirs[dirIndex][1];//需要加一個res[nextRow][nextCol] != 0 因為走了一圈之后就回到了原點,需要避免回原點,而是調整方向//比如三階矩陣中的最后9,若不調整方向,則會放到原點處if(nextRow < 0 || nextRow > n-1 || nextCol < 0 || nextCol > n-1 || res[nextRow][nextCol] != 0){dirIndex = (dirIndex+1) % 4;}curRow = curRow + dirs[dirIndex][0];curCol = curCol + dirs[dirIndex][1];}return res;}
}
方法2:層模擬
class Solution {public int[][] generateMatrix(int n) { int left = 0;int right = n-1;int top = 0;int bottom = n-1;int num = 1;int[][] res = new int[n][n];while(left <= right && top <= bottom){//上:從左往右-----j 從 left ---> rightfor(int j = left; j <= right; j++){res[top][j] = num++;}top++;//右:從上到下-----i 從 top ---> bottomfor(int i = top; i <= bottom; i++){res[i][right] = num++;}right--;if(top <= bottom){//下:從右到左-----j 從 right ---> leftfor(int j = right; j >= left; j--){res[bottom][j] = num++;}bottom--;}if(left <= right){//左:從下到上-----i 從 bottom ---> topfor(int i = bottom; i >= top; i--){res[i][left] = num++;}left++;}}return res;}
}
方法3:“循環畫框”
class Solution {public int[][] generateMatrix(int n) { int loopCur = 1; //當前所處的圈數int loopCnt = n / 2; //所需繪制的完整圈數int xStart = 0; //橫坐標的開始坐標int yStart = 0; //縱坐標的開始坐標int offset = 1; //當前繪制圈的偏置值int num = 1; //當前繪制的數字int i,j; //繪制地圖用的橫縱坐標int[][] res = new int[n][n];while(loopCur <= loopCnt){//上:從左往右-----j 從 yStart ---> n-offsetfor(j = yStart; j < n-offset; j++){res[xStart][j] = num++;}//右:從上到下-----i 從 xStart ---> n-offsetfor(i = xStart; i < n-offset; i++){res[i][j] = num++;}//下:從右到左-----j 遞減到 yStart+1for(; j > yStart; j--){res[i][j] = num++;}//左:從下到上-----i 遞減到 xStart+1for(; i > xStart; i--){res[i][j] = num++;}offset++; //調整偏置值loopCur++;xStart++;yStart++;}if(1 == n%2){res[xStart][yStart] = num;}return res;}
}
?(2)矩形樣式的螺旋矩陣
????????54.螺旋矩陣
方法1:點模擬
class Solution {public List<Integer> spiralOrder(int[][] matrix) {List<Integer> res = new ArrayList<Integer>();if(matrix == null){return res;}int rows = matrix.length;int cols = matrix[0].length;int cnt = rows * cols;if (rows == 0 || cols == 0) {return res;}int curRow = 0;int curCol = 0;int dirIndex = 0;int[][] dirs = {{0,1}, {1,0}, {0,-1}, {-1,0}};boolean[][] visited = new boolean[rows][cols];while(cnt > 0){res.add(matrix[curRow][curCol]);visited[curRow][curCol] = true;//判定后續位置是否越界int nextRow = curRow + dirs[dirIndex][0];int nextCol = curCol + dirs[dirIndex][1];//需要加一個res[nextRow][nextCol] != 0 因為走了一圈之后就回到了原點,需要避免回原點,而是調整方向//比如三階矩陣中的最后9,若不調整方向,則會放到原點處if(nextRow < 0 || nextRow > rows-1 || nextCol < 0 || nextCol > cols-1 || visited[nextRow][nextCol] != false){dirIndex = (dirIndex+1) % 4;}curRow = curRow + dirs[dirIndex][0];curCol = curCol + dirs[dirIndex][1];cnt--;}return res;}
}
方法2:層模擬
class Solution {public List<Integer> spiralOrder(int[][] matrix) {List<Integer> res = new ArrayList<Integer>();if(matrix == null){return res;}int rows = matrix.length;int cols = matrix[0].length;if (rows == 0 || cols == 0) {return res;}int top = 0;int bottom = rows -1;int left = 0;int right = cols -1;while(top <= bottom && left <= right){//上:從左到右for(int j = left; j <= right; j++){res.add(matrix[top][j]);}top++;//右:從上到下for(int i = top; i <= bottom; i++){res.add(matrix[i][right]);}right--;//下:從右到左if(top <= bottom){ //若不判斷,遇見單行,則會重復處理for(int j = right; j >= left;j--){res.add(matrix[bottom][j]);}}bottom--;//左:從下到上if(left <= right){ //若不判斷,遇見單列,則會重復處理for(int i = bottom; i >= top; i--){res.add(matrix[i][left]);}}left++;}return res;}
}
方法3:?“循環畫框”--錯誤代碼演示,沒改出來
class Solution {public List<Integer> spiralOrder(int[][] matrix) {List<Integer> res = new ArrayList<Integer>();int rows = matrix.length;int cols = matrix[0].length;int loopCur = 1;int loopCnt = rows/2 + 1; //為便捷處理中心區域的多個數據int xStart = 0;int yStart = 0;int offset = 1;//因為增加了圈數,導致單行的矩陣會重復打印if(rows == 1){for(int temp = 0; temp < cols; temp++){res.add(Integer.valueOf(matrix[0][temp]));}return res;}//因為增加了圈數,導致單列的矩陣會重復打印if(cols == 1){for(int temp = 0; temp < rows; temp++){res.add(Integer.valueOf(matrix[temp][0]));}return res;}int i,j;while(loopCur <= loopCnt){//上:從左到右for(j = yStart; j < cols-offset; j++){res.add(matrix[xStart][j]); }//右:從上到下for(i = xStart; i < rows-offset; i++){res.add(matrix[i][j]);}//下:從右到左for(; j > yStart; j--){res.add(matrix[i][j]);}//左:從下到上for(; i > xStart; i--){res.add(matrix[i][j]);}offset++;loopCur++;xStart++;yStart++;}if(rows == cols && rows%2 ==1){res.add(matrix[xStart-1][yStart-1]);}return res;}
}