Description

給定一個 n x n 的 2D 矩陣 matrix,將其原地順時針旋轉 90 度。不能使用額外的矩陣空間。

Example:

Input: matrix = [[1,2,3],[4,5,6],[7,8,9]] Output: [[7,4,1],[8,5,2],[9,6,3]]

Intuition#

核心思路:先沿主對角線轉置(transpose),再左右翻轉每一行,等同順時針旋轉 90 度。

  • 直接旋轉需要追蹤四個位置的循環交換,容易出錯
  • 拆解成兩步:轉置 + 翻轉,每步都很簡單
  • 順時針 90 度 = 轉置 + 左右翻轉;逆時針 90 度 = 轉置 + 上下翻轉

Approaches#

1: 四角循環交換#

  • 概念: 一圈一圈處理,每次同時交換四個角落的元素
  • 時間複雜度: O(n^2) - 每個元素恰好被訪問一次
  • 空間複雜度: O(1) - 原地操作
class Solution {
    fun rotate(matrix: Array<IntArray>) {
        val n = matrix.size
        for (layer in 0 until n / 2) {
            val last = n - 1 - layer
            for (i in layer until last) {
                val offset = i - layer
                val top = matrix[layer][i]
                // 左 -> 上
                matrix[layer][i] = matrix[last - offset][layer]
                // 下 -> 左
                matrix[last - offset][layer] = matrix[last][last - offset]
                // 右 -> 下
                matrix[last][last - offset] = matrix[i][last]
                // 上 -> 右
                matrix[i][last] = top
            }
        }
    }
}

⭐2: 轉置 + 翻轉#

  • 概念: 先沿主對角線轉置矩陣(交換 matrix[i][j] 和 matrix[j][i]),再左右翻轉每一行
  • 時間複雜度: O(n^2) - 兩次遍歷矩陣
  • 空間複雜度: O(1) - 原地操作
class Solution {
    fun rotate(matrix: Array<IntArray>) {
        val n = matrix.size
        // 轉置
        for (i in 0 until n) {
            for (j in i + 1 until n) {
                val temp = matrix[i][j]
                matrix[i][j] = matrix[j][i]
                matrix[j][i] = temp
            }
        }
        // 左右翻轉
        for (i in 0 until n) {
            var left = 0
            var right = n - 1
            while (left < right) {
                val temp = matrix[i][left]
                matrix[i][left] = matrix[i][right]
                matrix[i][right] = temp
                left++
                right--
            }
        }
    }
}
補充:旋轉方向整理
操作結果
轉置 + 左右翻轉順時針 90 度
轉置 + 上下翻轉逆時針 90 度
上下翻轉 + 左右翻轉旋轉 180 度

🔑 Takeaways#

  • Pattern: 矩陣旋轉可拆解為轉置 + 翻轉的組合
  • 關鍵技巧: 記住「轉置 + 左右翻轉 = 順時針 90 度」,面試中快速實作且不易出錯