力扣-54. 螺旋矩陣

DawnTraveler發表於2024-04-27

1.題目

題目地址(54. 螺旋矩陣 - 力扣(LeetCode))

https://leetcode.cn/problems/spiral-matrix/

題目描述

給你一個 mn 列的矩陣 matrix ,請按照 順時針螺旋順序 ,返回矩陣中的所有元素。

示例 1:

輸入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
輸出:[1,2,3,6,9,8,7,4,5]

示例 2:

輸入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
輸出:[1,2,3,4,8,12,11,10,9,5,6,7]

提示:

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= m, n <= 10
  • -100 <= matrix[i][j] <= 100

2.題解

2.1 模擬(圖論 + 標記)

思路

使用圖論中的方向陣列表示方向, 使用標記陣列visited標識哪些元素被訪問過了,一旦遇到邊界或者遇到被訪問過的標記就轉向即可
標記方式不止一種, 這裡也可以直接將遍歷過的元素取負值或者賦值為INT_MAX均可

注意判斷這裡: if(dx < 0 || dx >= row || dy < 0 || dy >= col || visited[dx][dy])
一定要使用熔斷機制, 將visited[dx][dy] 放在最後, 否則就會發生陣列越界!!!

程式碼

  • 語言支援:C++

C++ Code:


class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        int row = matrix.size(), col = matrix[0].size();
        vector<vector<int>> visited(row, vector<int>(col, 0));
        vector<pair<int, int>> dir{{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
        int cnt = 0, x = 0, y = 0;
        vector<int> ans;
        for(int i = 0; i < row * col; i++){
            ans.push_back(matrix[x][y]);
            visited[x][y] = 1;
            int dx = x + dir[cnt].first;
            int dy = y + dir[cnt].second; 
            if(dx < 0 || dx >= row || dy < 0 || dy >= col || visited[dx][dy]){
                cnt = (cnt + 1) % 4;
                dx = x + dir[cnt].first;
                dy = y + dir[cnt].second; 
            }
            x = dx;
            y = dy;
        }
        return ans;
    }
};

複雜度分析

令 n 為陣列長度。

  • 時間複雜度:\(O(m * n)\)
  • 空間複雜度:\(O(m * n)\)

2.2

思路

可以將矩陣看成若干層,首先輸出最外層的元素,其次輸出次外層的元素,直到輸出最內層的元素。
定義矩陣的第 k 層是到最近邊界距離為 k 的所有頂點。例如,下圖矩陣最外層元素都是第 1 層,次外層元素都是第 2 層,剩下的元素都是第 3 層。
每一層的rowBegin, rowEnd, colBegin, colEnd都不同, 每次遍歷完一行/一列便更新即可!

程式碼

class Solution {
public:
    vector<int> spiralOrder(vector<vector<int>>& matrix) {
        int rowBegin = 0, rowEnd = matrix.size() - 1;    // 行
        int colBegin = 0, colEnd = matrix[0].size() - 1; // 列
        vector<int> ans;
        while (true) {
            // 從左向右遍歷(行)
            for (int i = colBegin; i <= colEnd; i++)
                ans.push_back(
                    matrix[rowBegin][i]); // rowBegin 這行已經遍歷過了,
                                          // 下次不可以再遍歷, ++rowBegin
            if (++rowBegin > rowEnd)
                break;

            // 從上向下遍歷(列)
            for (int i = rowBegin; i <= rowEnd; i++)
                ans.push_back(matrix[i][colEnd]); // colEnd 這列已經遍歷過了,
                                                  // 下次不可以再遍歷, --colEnd
            if (--colEnd < colBegin)
                break;

            // 從右向左遍歷(行)
            for (int i = colEnd; i >= colBegin; i--)
                ans.push_back(matrix[rowEnd][i]);
            if (--rowEnd < rowBegin)
                break;

            // 從下向上遍歷(列)
            for (int i = rowEnd; i >= rowBegin; i--)
                ans.push_back(matrix[i][colBegin]);
            if(++colBegin > colEnd)
                break;
        }
        return ans;
    }
};

複雜度分析

令 n 為陣列長度。

  • 時間複雜度:\(O(m * n)\)
  • 空間複雜度:\(O(1)\)

相關文章