↓Skip to main content
  1. LeetCode/

LeetCode 2968: Apply Operations to Maximize Frequency Score

·2 mins· ·
LeetCode Hard Sliding-Window Sorting Prefix-Sum Binary-Search Array
Wei Yi Chung
Author
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
Table of Contents

Meta Data
#

Difficulty: hard First Attempt: 2026-01-18

  • Submissions: Accepted (first try)

Approach
#

Much like LeetCode 1838, except values can move both up and down.

  1. The numbers made equal always form a contiguous block after sorting.
  2. Making a block equal costs Σ |x - target|, and the cheapest target is the median.
  3. With prefix sums the cost is O(1), using mid = (left + right) // 2:
left half:  nums[mid] × (mid - left + 1) − sum(nums[left..mid])
right half: sum(nums[mid+1..right]) − nums[mid] × (right - mid)

The cost never decreases as the window grows, so use the “longest” sliding window: shrink the left while the cost is > k.

My Solution
#

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:         # make nums[lo..hi] equal to the median
            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

Complexity
#

Time O(n log n), space O(n).

Mistakes to Avoid
#

  • Targeting the mean: the sum of absolute differences is minimized at the median, not the mean.
  • Re-summing the window each time: use prefix sums.

Interview Explanation
#

The numbers made equal form a contiguous block after sorting, and the target minimizing the sum of absolute differences is the median. Prefix sums give the cost of moving a block to its median in O(1); that cost grows with the window, so I slide and shrink the left when it exceeds k. Sorting dominates: O(n log n).

Related

LeetCode 2302: Count Subarrays With Score Less Than K
·2 mins
LeetCode Hard Sliding-Window Prefix-Sum Binary-Search Array
LeetCode 2302 note: score = sum × length with positive numbers grows with the window; shrink while the score is >= k, and right - left + 1 valid subarrays end at right
LeetCode 1838: Frequency of the Most Frequent Element
·2 mins
LeetCode Medium Sliding-Window Sorting Greedy Prefix-Sum Binary-Search Array
LeetCode 1838 note: after sorting, raising the whole window to nums[right] costs nums[right] × length − window sum; shrink the left while that exceeds k
LeetCode 2271: Maximum White Tiles Covered by a Carpet
·2 mins
LeetCode Medium Sliding-Window Greedy Sorting Prefix-Sum Binary-Search Array
LeetCode 2271 note: starting the carpet at some segment’s start is never worse; after sorting, two pointers sum the fully covered segments and count the last one partially
LeetCode 3413: Maximum Coins From K Consecutive Bags
·3 mins
LeetCode Medium Sliding-Window Greedy Sorting Prefix-Sum Binary-Search Array
LeetCode 3413 note: the best k bags always have one end on a segment boundary; compute “left end at a segment start” and “right end at a segment end” (the latter by mirroring and reusing the same function)
LeetCode 2106: Maximum Fruits Harvested After at Most K Steps
·2 mins
LeetCode Hard Sliding-Window Prefix-Sum Binary-Search Array
LeetCode 2106 note: the harvest is always a contiguous block of fruits; covering [L, R] takes (R - L) + min(|start - L|, |R - start|) steps, so slide a window over the fruits array
LeetCode 3634: Minimum Removals to Balance Array
·2 mins
LeetCode Medium Sliding-Window Sorting Binary-Search Array
LeetCode 3634 note: after sorting, what remains is always a contiguous block; for each minimum nums[left], a right-only pointer finds how far it can extend, and everything outside is removed