LC 2968. 执行操作使频率分数最大

https://leetcode.cn/problems/apply-operations-to-maximize-frequency-score/description/

这题需要稍微想象一下,首先众数肯定是nums其中某个数,我们对nums做个排序。

假设众数是 `nums[i]` 的话,并且从左边 left 变过来,从最右边 rigth 变过来,那么就有个要求是 \(sum_{j=left}^{i-}(nums[i]-nums[j]) + sum_{j=i+1}^{right}(nums[j] - nums[i]) <= k\) . 得到的众数频数是 `right - left + 1`.

然后从i->i+1开始进行移动:

在这个过程中需要保证 k>=0:

这样就完成了i->i+1的更新,更新之后left, right都会变化,众数频数就是 `right-left+1`.

下面的代码稍微有点乱,分支有点多。

class Solution:
    def maxFrequencyScore(self, nums: List[int], k: int) -> int:
        nums.sort()
        from collections import deque
        left = deque([0])
        right = 0

        while right < len(nums):
            diff = nums[right] - nums[0]
            if k >= diff:
                right += 1
                k -= diff
            else:
                break

        assert (k >= 0)
        ans = right - left[0]
        for i in range(1, len(nums)):
            move = nums[i] - nums[i - 1]
            k -= len(left) * move
            k += move * (right - i)

            # balance left and right
            while right < len(nums) and left:
                r = nums[right] - nums[i]
                l = nums[i] - nums[left[0]]
                if r <= l:
                    k += l
                    k -= r
                    left.popleft()
                    right += 1
                else:
                    break

            # check k is sastified.
            while k < 0:
                l, r = -1, -1
                if left:
                    l = nums[i] - nums[left[0]]
                if right > i:
                    r = nums[right - 1] - nums[i]
                if (l, r) == (-1, -1): break
                if l >= r:
                    k += l
                    left.popleft()
                else:
                    k += r
                    right -= 1
            assert (k >= 0)

            while k >= 0:
                INF = 1 << 63
                l, r = INF, INF

                idx = i - 1
                if left:
                    idx = left[0] - 1
                if idx >= 0:
                    l = nums[i] - nums[idx]
                if right < len(nums):
                    r = nums[right] - nums[i]
                if (l, r) == (INF, INF): break
                if k < min(l, r): break
                if l >= r:
                    k -= r
                    right += 1
                else:
                    k -= l
                    left.appendleft(idx)

            assert (k >= 0)
            left.append(i)
            size = right - left[0]
            ans = max(ans, size)
        return ans