Medium草稿★★★★★O(log n) 時間 · O(1) 空間
ArrayBinary Search
Patterns🎯 二分搜尋
尚未複習過

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

81Search In Rotated Sorted Array IIBinary SearchMediumBinary Search

在一個可能含有重複元素的旋轉排序陣列中搜尋目標值 target。回傳是否存在。(延伸自 #33,但允許重複元素。)

Example:

Input: nums = [2,5,6,0,0,1,2], target = 0 Output: true

Intuition

TIP

與 #33 相同邏輯,但遇到 nums[left] == nums[mid] == nums[right] 時無法判斷哪邊有序,需要收縮邊界。

Approaches

1. Linear Scan — O(n) / O(1)
  • Idea: 直接遍歷陣列查找
  • Time: O(n)
  • Space: O(1)
Linear Scan Code
class Solution {
    fun search(nums: IntArray, target: Int): Boolean {
        return target in nums
    }
}
⭐ 2. Binary Search (handle duplicates) — O(log n) / O(1)
  • Idea: 二分搜尋,遇到無法判斷的情況就收縮邊界
  • Time: O(log n) 平均,O(n) 最差(全部重複時)
  • Space: O(1)
class Solution {
    fun search(nums: IntArray, target: Int): Boolean {
        var left = 0
        var right = nums.size - 1
        while (left <= right) {
            val mid = left + (right - left) / 2
            if (nums[mid] == target) return true

            // 無法判斷哪邊有序,收縮邊界
            if (nums[left] == nums[mid] && nums[mid] == nums[right]) {
                left++
                right--
            } else if (nums[left] <= nums[mid]) {
                // 左半部有序
                if (target >= nums[left] && target < nums[mid]) {
                    right = mid - 1
                } else {
                    left = mid + 1
                }
            } else {
                // 右半部有序
                if (target > nums[mid] && target <= nums[right]) {
                    left = mid + 1
                } else {
                    right = mid - 1
                }
            }
        }
        return false
    }
}

WARNING

最差情況如 [1,1,1,1,1,1,2,1,1] 搜尋 2,每次只能縮小一格,退化為 O(n)。這是有重複元素的代價。

🔑 Takeaways

Ladders 看全部 →

🔍

二分搜尋進階

從基本模板到旋轉陣列與重複值。

  1. 1#704Binary SearchEasy有序陣列的基本二分模板
  2. 2#35Search Insert PositionEasy找插入位置(lower_bound)
  3. 3#33Search in Rotated Sorted ArrayMedium旋轉排序陣列中找目標
  4. 4
  5. 5#153Find Minimum in Rotated Sorted ArrayMedium找旋轉陣列的最小值
  6. 6