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

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

540Single Element in a Sorted ArrayBinary SearchMediumBinary Search

給定一個排序陣列,其中每個元素恰好出現兩次,只有一個元素只出現一次。找出這個只出現一次的元素。要求 O(log n) 時間複雜度和 O(1) 空間複雜度。

Example:

Input: nums = [1,1,2,3,3,4,4,8,8] Output: 2

Intuition

TIP

在單獨元素之前,成對元素的首個出現在偶數索引;在之後,首個出現在奇數索引。利用此規律二分搜尋。

Approaches

1. XOR — O(n) / O(1)
  • Idea: 全部 XOR 起來,成對的會互相抵消,剩下的就是答案
  • Time: O(n)
  • Space: O(1)
XOR Code
class Solution {
    fun singleNonDuplicate(nums: IntArray): Int {
        var result = 0
        for (num in nums) {
            result = result xor num
        }
        return result
    }
}
⭐ 2. Binary Search — O(log n) / O(1)
  • Idea: 在偶數索引上二分搜尋,檢查 nums[mid] == nums[mid+1] 判斷單獨元素在左邊還是右邊
  • Time: O(log n)
  • Space: O(1)
class Solution {
    fun singleNonDuplicate(nums: IntArray): Int {
        var left = 0
        var right = nums.size - 1
        while (left < right) {
            var mid = left + (right - left) / 2
            // 確保 mid 是偶數索引
            if (mid % 2 == 1) mid--
            if (nums[mid] == nums[mid + 1]) {
                // 成對規律正常,單獨元素在右邊
                left = mid + 2
            } else {
                // 規律被破壞,單獨元素在左邊(含 mid)
                right = mid
            }
        }
        return nums[left]
    }
}

WARNING

關鍵是確保 mid 落在偶數索引上,這樣才能正確判斷成對規律。若 mid 是奇數,先減 1。

🔑 Takeaways