\Delta(l, r + 1) - \Delta(l, r) = (x_{r + 1} - x_{r})\cdot(r - l + 1) \ge 0.
操作数有可能超过限制 k,因此在超过限制的情况下,我们需要移动左边界 l。同样考虑左边界 l 右移至 l + 1 的过程,此时:
\Delta(l + 1, r + 1) - \Delta(l, r + 1) = -(x_{r + 1} - x_{l}) \le 0.
这说明右移左边界会使得答案减小,因此我们需要移动左边界直至对应的 \Delta(l’, r + 1) 不大于 k。
我们使用 l 与 r 作为执行操作的左右边界(闭区间),同时用 total 来维护将 [l, r] 区间全部变为末尾元素的操作次数。在顺序枚举目标值(右边界)的同时,我们更新对应的左边界,并用 res 来维护满足限制的最大区间元素数量即可。
另外要注意,此处 total 有可能会超过 32 位整数的范围,因此在 C++ 等语言中需要使用更高位数的整型变量(long long 等)。
代码
[sol1-C++]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
classSolution { public: intmaxFrequency(vector<int>& nums, int k){ sort(nums.begin(), nums.end()); int n = nums.size(); longlong total = 0; int l = 0, res = 1; for (int r = 1; r < n; ++r) { total += (longlong)(nums[r] - nums[r - 1]) * (r - l); while (total > k) { total -= nums[r] - nums[l]; ++l; } res = max(res, r - l + 1); } return res; } };
[sol1-Java]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
classSolution { publicintmaxFrequency(int[] nums, int k) { Arrays.sort(nums); intn= nums.length; longtotal=0; intl=0, res = 1; for (intr=1; r < n; ++r) { total += (long) (nums[r] - nums[r - 1]) * (r - l); while (total > k) { total -= nums[r] - nums[l]; ++l; } res = Math.max(res, r - l + 1); } return res; } }
[sol1-C#]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
publicclassSolution { publicintMaxFrequency(int[] nums, int k) { Array.Sort(nums); int n = nums.Length; long total = 0; int l = 0, res = 1; for (int r = 1; r < n; ++r) { total += (long) (nums[r] - nums[r - 1]) * (r - l); while (total > k) { total -= nums[r] - nums[l]; ++l; } res = Math.Max(res, r - l + 1); } return res; } }
[sol1-Python3]
1 2 3 4 5 6 7 8 9 10 11 12 13 14
classSolution: defmaxFrequency(self, nums: List[int], k: int) -> int: nums.sort() n = len(nums) l = 0 total = 0 res = 1 for r inrange(1, n): total += (nums[r] - nums[r - 1]) * (r - l) while total > k: total -= nums[r] - nums[l] l += 1 res = max(res, r - l + 1) return res
[sol1-JavaScript]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
var maxFrequency = function(nums, k) { nums.sort((a, b) => a - b); const n = nums.length; let total = 0, res = 1, l = 0;
for (let r = 1; r < n; r++) { total += (nums[r] - nums[r - 1]) * (r - l); while (total > k) { total -= nums[r] - nums[l]; l += 1; } res = Math.max(res, r - l + 1); } return res; };
funcmaxFrequency(nums []int, k int)int { sort.Ints(nums) ans := 1 for l, r, total := 0, 1, 0; r < len(nums); r++ { total += (nums[r] - nums[r-1]) * (r - l) for total > k { total -= nums[r] - nums[l] l++ } ans = max(ans, r-l+1) } return ans }
funcmax(a, b int)int { if a > b { return a } return b }
[sol1-C]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
intcmp(int *a, int *b) { return *a - *b; }
intmaxFrequency(int *nums, int numsSize, int k) { qsort(nums, numsSize, sizeof(int), cmp); int n = numsSize; longlong total = 0; int l = 0, res = 1; for (int r = 1; r < n; ++r) { total += (longlong)(nums[r] - nums[r - 1]) * (r - l); while (total > k) { total -= nums[r] - nums[l]; ++l; } res = fmax(res, r - l + 1); } return res; }
复杂度分析
时间复杂度:O(n\log n),其中 n 是数组 nums 的长度。排序数组的时间复杂度为 O(n\log n),使用滑动窗口遍历目标值的时间复杂度为 O(n)。