MediumRating 1876
1838. Frequency of the Most Frequent Element
arraybinary-searchgreedysliding-windowsortingprefix-sum
解題說明
Frequency of the Most Frequent Element
題目描述:
給定一個整數陣列 nums 和整數 k。每次操作可以選擇一個元素並將其值加 1。最多執行 k 次操作後,求陣列中出現頻率最高的元素的最大可能頻率。
解題思路: 排序 + 滑動窗口。
- 將陣列排序。排序後,我們想找到一個最長的連續子陣列,使得可以用最多 k 次操作將所有元素都提升到子陣列中的最大值。
- 維護滑動窗口
[left, right],目標是把所有元素都變成nums[right]。 - 所需操作數 =
nums[right] * 窗口長度 - 窗口元素之和。 - 若所需操作數 > k,則收縮左邊界。
- 答案為窗口的最大長度。
C++ 解法
複雜度分析
時間複雜度:O(n log n) — 排序 O(n log n),滑動窗口遍歷 O(n),以排序為主。
空間複雜度:O(log n) — 排序所需的棧空間(原地排序)。
虛擬碼
1. Sort nums in ascending order
2. Initialize left = 0, sum = 0, ans = 1
3. For each right from 0 to n-1:
a. sum += nums[right]
b. While nums[right] * (right - left + 1) - sum > k:
- sum -= nums[left]
- left++
c. ans = max(ans, right - left + 1)
4. Return ans其他解法
二分搜尋 + 前綴和 O(n log n):對答案(頻率)進行二分搜尋。對於給定頻率 f,用前綴和在 O(n) 時間檢查是否存在長度為 f 的窗口使得操作數 <= k。邏輯更模組化但常數因子稍大。
暴力枚舉 O(n²):對每個右端點,線性向左擴展窗口。簡單但 n 大時超時。
延伸思考
- 如果每次操作可以加 1 或減 1(雙向操作),最大頻率會如何變化?
- 如果操作有成本(不同元素操作成本不同),如何修改滑動窗口的條件?
- 如果陣列是動態更新的(插入/刪除元素),如何高效維護答案?