ACM之螺旋矩陣

題目如下

圖片.png

分析

       不難發現,按照順時針螺旋順序遍歷矩陣其實就只有四個方向:頂層行從左往右;右邊列從上到下;底層行從右往左;左邊列從下往上。遍歷完這四個方向之後就表示已經遍歷完了一圈,下一圈也同樣是這四個方向,只是初始位置和結束位置會在每一輪遍歷之後發生變化。

       下面介紹兩種方法,思想基本一致,不同之處是對邊界的判斷和位置的移動。

方法一

public class SpiralMatrix {
     public static List<Integer> spiralMatrixOlder(int[][] matrix) {
          List<Integer> res = new ArrayList<Integer>();
          if(matrix.length == 0)
              return res;
          
          int rowBegin = 0;
          int colBegin = 0;
          int rowEnd = matrix.length - 1; //行
          int colEnd = matrix[0].length - 1; //列
          
          /*
           * Time Complexity: O(N)
           * Space Complexity:O(N)*/
          while(rowBegin <= rowEnd && colBegin <= colEnd){
              
                   //底層行從左往右
                   for(int i = colBegin;i <= colEnd;i++) {
                        res.add(matrix[rowBegin][i]);
                   }
                   rowBegin++; //處理完一行後往下移一行
                   
                   //右邊列從上往下
                   for(int i = rowBegin ;i <= rowEnd;i++) {
                        res.add(matrix[i][colEnd]);
                   }
                   colEnd--; //處理完一列往前移一列
                   
                   //底層行從右往左
                   if(rowBegin <= rowEnd) {
                        for(int j = colEnd;j>=colBegin;j--){
                             res.add(matrix[rowEnd][j]);
                        }
                        rowEnd--;
                   }
                   
                   //左邊列從下往上
                   if(colBegin <= colEnd) {
                        for(int j = rowEnd;j >= rowBegin ; j--) {
                             res.add(matrix[j][colBegin]);
                        }
                        colBegin++;
                   }
                   
          }
          return res;
          
     }


方法二   

   設數組有R行和C列。 seen[r] [c] = ture表示先前訪問過第r行和第c列的元素。 我們當前的位置是(r,c),面向方向di,我們想要訪問R x C個全部元素。

   當我們在矩陣中移動時,我們的候選下一個位置是(cr,cc)。 如果候選位置處於矩陣的邊界並且看不見(即seen[cr][cc] = false),那麼它就成了我們的下一個位置; 否則,我們的下一個位置是順時針轉彎後的位置。

public class SpiralMatrixBter {
     public List<Integer> spiralMatrixOlder(int [][] matrix) {
          List<Integer> res = new ArrayList<Integer>();
          if(matrix.length == 0) return res;
          int rowLen = matrix.length;
          int colLen = matrix[0].length;
          boolean[][] seen = new boolean[rowLen][colLen];
     
          //頂層行遍歷時:row+=0,col+=1
          //右邊列遍歷時:row+=1,col+=0
          //底層行遍歷時:row+=0,col+=-1
          //左邊列遍歷時:row+=-1,col+=0
          //把上面的信息存儲到數組中
          int[] dr = {0,1,0,-1};
          int[] dc = {1,0,-1,0};
          int row = 0;
          int col = 0;
          int di = 0;
          for(int i = 0;i < rowLen*colLen;i++) {
              res.add(matrix[row][col]);
              seen[row][col] = true; //表示此節點已被讀取
    
              int cr = row + dr[di];
              int cc = col + dc[di];
              
              if(cr >= 0 && cr <rowLen && cc >= 0 && cc < colLen && !seen[cr][cc]) {
                   row = cr;
                   col = cc;
              }else{
                   di = (di + 1) % 4;
                   row += dr[di];
                   col += dc[di];
              }              
          }                   
          return res;
     }


Python實現

def spiralOrder(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: List[int]
        """
        ret = []
        while matrix:
            ret += matrix.pop(0)
            if matrix and matrix[0]:
                for row in matrix:
                    ret.append(row.pop())
            if matrix:
                ret += matrix.pop()[::-1]
            if matrix and matrix[0]:
                for row in matrix[::-1]:
                    ret.append(row.pop(0))
        return ret





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章