↓快轉到主要內容
  1. LeetCode/

LeetCode 2968: Apply Operations to Maximize Frequency Score

·1 分鐘· ·
LeetCode Hard Sliding-Window Sorting Prefix-Sum Binary-Search Array
Wei Yi Chung
作者
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
目錄

基本資料
#

難易度: hard 第一次嘗試:2026-01-18

  • 提交紀錄:Accepted(一次通過)

解題思路
#

跟 LeetCode 1838 很像,但這題可以加也可以減。

  1. 要變成同一個值的那些數,排序後一定是連續的一段。
  2. 把一段數都變成同一個值,花費是 Σ |x - target|,最省的 target 是中位數。
  3. 用前綴和 O(1) 算花費,mid = (left + right) // 2:
左半:nums[mid] × (mid - left + 1) − sum(nums[left..mid])
右半:sum(nums[mid+1..right]) − nums[mid] × (right - mid)

視窗變大時花費不會變小,所以用「求最長」的滑動視窗:花費 > k 就縮左邊。

我的解法
#

class Solution:
    def maxFrequencyScore(self, nums: List[int], k: int) -> int:
        nums.sort()
        prefix = [0]
        for x in nums:
            prefix.append(prefix[-1] + x)

        def cost(lo: int, hi: int) -> int:         # 把 nums[lo..hi] 都變成中位數
            mid = (lo + hi) // 2
            target = nums[mid]
            left_cost = target * (mid - lo + 1) - (prefix[mid + 1] - prefix[lo])
            right_cost = (prefix[hi + 1] - prefix[mid + 1]) - target * (hi - mid)
            return left_cost + right_cost

        left = best = 0
        for right in range(len(nums)):
            while cost(left, right) > k:
                left += 1
            best = max(best, right - left + 1)
        return best

複雜度
#

時間 O(n log n),空間 O(n)。

要特別避免的錯誤
#

  • 目標值用平均數:絕對值總和的最小值在中位數,不是平均數。
  • 每次重新加總視窗:要用前綴和。

面試口說整理
#

要變成同一個值的數,排序後一定是連續的一段,而絕對值總和最小的目標是中位數。我用前綴和 O(1) 算把一段變成中位數的花費,這個花費隨視窗變大而變大,所以用滑動視窗,超過 k 就縮左邊。時間由排序決定,O(n log n)。

相關文章

LeetCode 2302: Count Subarrays With Score Less Than K
·1 分鐘
LeetCode Hard Sliding-Window Prefix-Sum Binary-Search Array
LeetCode 2302 解題筆記:分數 = 總和 × 長度,都是正數,視窗越大分數越大;分數 >= k 就縮左邊,以 right 結尾的合法子陣列有 right - left + 1 個
LeetCode 1838: Frequency of the Most Frequent Element
·1 分鐘
LeetCode Medium Sliding-Window Sorting Greedy Prefix-Sum Binary-Search Array
LeetCode 1838 解題筆記:排序後,把視窗裡的數都加到 nums[right] 的花費是 nums[right] × 長度 − 視窗總和;花費 > k 就縮左邊
LeetCode 2271: Maximum White Tiles Covered by a Carpet
·1 分鐘
LeetCode Medium Sliding-Window Greedy Sorting Prefix-Sum Binary-Search Array
LeetCode 2271 解題筆記:地毯的左端放在某段白磚的起點一定不會更差;排序後用雙指針,完整蓋住的段累加,最後一段只算部分
LeetCode 3413: Maximum Coins From K Consecutive Bags
·2 分鐘
LeetCode Medium Sliding-Window Greedy Sorting Prefix-Sum Binary-Search Array
LeetCode 3413 解題筆記:最佳的 k 個袋子,一定有一端對齊某段的端點;分別算「左端對齊段的起點」和「右端對齊段的終點」(鏡像後重用同一個函式)
LeetCode 2106: Maximum Fruits Harvested After at Most K Steps
·1 分鐘
LeetCode Hard Sliding-Window Prefix-Sum Binary-Search Array
LeetCode 2106 解題筆記:採到的一定是連續一段水果;走完 [L, R] 的最少步數是 (R - L) + min(|start - L|, |R - start|),在水果陣列上用滑動視窗
LeetCode 3634: Minimum Removals to Balance Array
·1 分鐘
LeetCode Medium Sliding-Window Sorting Binary-Search Array
LeetCode 3634 解題筆記:排序後留下來的一定是連續一段;對每個最小值 nums[left],用只往右走的指針找能留到哪裡,刪掉兩邊剩下的