Medium草稿★★★★O(n) 時間 · O(1) 空間
Two PointersArrayBinary Search
Patterns🎯 二分搜尋↔️ 雙指針
尚未複習過

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

167Two Sum II - Input Array Is SortedTwo PointersMediumTwo Pointers

給定一個已按非遞減排序的整數陣列 numbers(1-indexed),找出兩個數使它們的和等於 target,回傳這兩個數的索引(1-based)。保證恰好有一組解,且不能使用同一元素兩次。

Example:

Input: numbers = [2,7,11,15], target = 9 Output: [1,2]

Intuition

TIP

核心思路:已排序陣列,用左右指針,和太大右移左、和太小右移右,O(n) 搞定。

Approaches

1. Binary Search — O(n log n) / O(1)
  • Idea: 對每個元素 numbers[i],用二分搜尋在剩餘部分尋找 target - numbers[i]
  • Time: O(n log n) - 外層 O(n),內層二分 O(log n)
  • Space: O(1)
class Solution {
    fun twoSum(numbers: IntArray, target: Int): IntArray {
        for (i in numbers.indices) {
            val complement = target - numbers[i]
            var lo = i + 1
            var hi = numbers.size - 1

            while (lo <= hi) {
                val mid = lo + (hi - lo) / 2
                when {
                    numbers[mid] == complement -> return intArrayOf(i + 1, mid + 1)
                    numbers[mid] < complement -> lo = mid + 1
                    else -> hi = mid - 1
                }
            }
        }

        throw IllegalArgumentException("No solution found")
    }
}
⭐ 2. Two Pointers — O(n) / O(1)
  • Idea: 左指針從頭、右指針從尾開始,根據當前和與 target 的比較移動指針
  • Time: O(n) - 每步至少移動一個指針,最多 n 步
  • Space: O(1) - 只用兩個指針
class Solution {
    fun twoSum(numbers: IntArray, target: Int): IntArray {
        var left = 0
        var right = numbers.size - 1

        while (left < right) {
            val sum = numbers[left] + numbers[right]
            when {
                sum == target -> return intArrayOf(left + 1, right + 1)
                sum < target -> left++
                else -> right--
            }
        }

        throw IllegalArgumentException("No solution found")
    }
}

WARNING

注意回傳的是 1-based 索引,別忘了 +1。另外 sum 可能溢位 Int 範圍,但此題測資保證不會。

🔑 Takeaways

Ladders 看全部 →

Two Sum 家族

從雜湊配對,到排序雙指針,再推廣到 k-sum。

  1. 1#1Two SumEasy雜湊表存補數,一次遍歷配對
  2. 2
  3. 3#153SumMedium固定一數 + 雙指針找另兩數,處理去重
  4. 4#184SumMedium再加一層迴圈,一般化成 k-sum