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

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

33Search in Rotated Sorted ArrayBinary SearchMediumBinary Search

給定一個旋轉過的升序整數陣列 nums(元素不重複)和一個目標值 target,搜尋 target 是否存在於陣列中。如果存在回傳其索引,否則回傳 -1。要求時間複雜度為 O(log n)

Example:

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

Intuition

TIP

旋轉陣列的左右半部至少有一邊是有序的,先判斷哪半邊有序,再決定 target 是否落在有序的那一半。

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): Int {
        for (i in nums.indices) {
            if (nums[i] == target) return i
        }
        return -1
    }
}
⭐ 2. Binary Search — O(log n) / O(1)
  • Idea: 每次判斷哪半邊有序,再判斷 target 是否在有序的那一半中
  • Time: O(log n)
  • Space: O(1)
class Solution {
    fun search(nums: IntArray, target: Int): Int {
        var left = 0
        var right = nums.size - 1
        while (left <= right) {
            val mid = left + (right - left) / 2
            if (nums[mid] == target) return mid
            // 左半部有序
            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 -1
    }
}

WARNING

判斷左半部有序時用 nums[left] <= nums[mid](含等號),因為當 left == mid 時(只剩兩個元素),左半部只有一個元素,也算有序。

🔑 Takeaways

Ladders 看全部 →

🔍

二分搜尋進階

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

  1. 1#704Binary SearchEasy有序陣列的基本二分模板
  2. 2#35Search Insert PositionEasy找插入位置(lower_bound)
  3. 3
  4. 4#81Search In Rotated Sorted Array IIMedium旋轉陣列含重複 → 處理邊界相等
  5. 5#153Find Minimum in Rotated Sorted ArrayMedium找旋轉陣列的最小值
  6. 6