Easy草稿★★★★★O(n) 時間 · O(k) 空間
Sliding WindowHash MapArray
Patterns🪟 滑動視窗#️⃣ 雜湊
尚未複習過

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

219Contains Duplicate IISliding WindowEasySliding Window

給定整數陣列 nums 和整數 k,判斷是否存在兩個不同的索引 ij,使得 nums[i] == nums[j]|i - j| <= k

Example:

Input: nums = [1,2,3,1], k = 3 Output: true

Intuition

TIP

核心思路:維護一個大小最多為 k 的滑動視窗(HashSet),檢查新元素是否已在視窗中。

Approaches

1. Brute Force - Double Loop — O(n * k) / O(1)
  • Idea: 對每個 i,檢查 i+1 到 i+k 範圍內是否有相同元素
  • Time: O(n * k) - 最差情況
  • Space: O(1)
Brute Force Code
class Solution {
    fun containsNearbyDuplicate(nums: IntArray, k: Int): Boolean {
        for (i in nums.indices) {
            for (j in i + 1..minOf(i + k, nums.size - 1)) {
                if (nums[i] == nums[j]) return true
            }
        }
        return false
    }
}
⭐ 2. Sliding Window + HashSet — O(n) / O(k)
  • Idea: 用 HashSet 維護大小為 k 的視窗,每步加入新元素前檢查是否已存在;若視窗超過 k,移除最左邊的元素
  • Time: O(n) - 每個元素加入和移除各一次
  • Space: O(k) - HashSet 最多存 k 個元素
class Solution {
    fun containsNearbyDuplicate(nums: IntArray, k: Int): Boolean {
        val window = HashSet<Int>()
        for (i in nums.indices) {
            if (nums[i] in window) return true
            window.add(nums[i])
            if (window.size > k) {
                window.remove(nums[i - k])
            }
        }
        return false
    }
}

WARNING

移除的是 nums[i - k] 而非 nums[i - k + 1],因為新元素已加入後視窗大小為 k+1,要移除最早的那個。

🔑 Takeaways