Medium草稿★★★★O(m + n) 時間 · O(1) 空間
ArrayBinary SearchMatrixDivide and Conquer
Patterns🎯 二分搜尋✂️ 分治
尚未複習過

解法已隱藏 — 先讀題目敘述、自己想想看,再點上方按鈕揭曉。

240Search a 2D Matrix IIBinary SearchMediumBinary Search

在一個 m x n 矩陣中搜尋目標值 target。矩陣性質:每列由左到右遞增、每行由上到下遞增(注意:不像 74 那樣整體展平後有序,行尾不一定小於下一行行首)。

Example:

Input: matrix = [[ 1, 4, 7,11,15], [ 2, 5, 8,12,19], [ 3, 6, 9,16,22], [10,13,14,17,24], [18,21,23,26,30]], target = 5 Output: true

Input: 同上, target = 20 Output: false

Intuition

TIP

核心思路:從右上角出發。該位置是所在列的最大、所在行的最小——比 target 大就往左砍一整列尾、比 target 小就往下砍一整行頭,每步排除一行或一列。

Approaches

1. Binary Search Each Row — O(m log n) / O(1)
  • Idea: 每列都有序,逐列二分找 target
  • Time: O(m log n) - m 列、每列二分 O(log n)
  • Space: O(1)
class Solution {
    fun searchMatrix(matrix: Array<IntArray>, target: Int): Boolean {
        for (row in matrix) {
            var lo = 0; var hi = row.size - 1
            while (lo <= hi) {
                val mid = (lo + hi) ushr 1
                when {
                    row[mid] == target -> return true
                    row[mid] < target -> lo = mid + 1
                    else -> hi = mid - 1
                }
            }
        }
        return false
    }
}
⭐ 2. Staircase Search from Top-Right — O(m + n) / O(1)
  • Idea: 利用「右上角往左變小、往下變大」每步排除一行或一列
  • Time: O(m + n) - 每步 row++ 或 col—
  • Space: O(1)
class Solution {
    fun searchMatrix(matrix: Array<IntArray>, target: Int): Boolean {
        if (matrix.isEmpty() || matrix[0].isEmpty()) return false
        var row = 0
        var col = matrix[0].size - 1
        while (row < matrix.size && col >= 0) {
            val cur = matrix[row][col]
            when {
                cur == target -> return true
                cur > target -> col--   // 排除這一行右側
                else -> row++           // 排除這一列上方
            }
        }
        return false
    }
}

🔑 Takeaways