DeepSeek LeetCode 2968. 执行操作使频率分数最大 Java实现
发布时间:2026/6/4 11:56:02
分类:文化教育
浏览:1234

好的我们来看 LeetCode 2968. 执行操作使频率分数最大。题目理解给定一个数组 nums 和一个整数 k你可以对任意元素进行最多 k 次操作每次操作可以让某个元素的值增加 1 或减少 1。目标经过最多 k 次操作后使得数组中某个值的出现频率即相同数字的个数最大返回这个最大频率。换句话说我们可以将一些数字通过增减操作变成同一个值消耗次数等于与目标值的绝对差之和问在总操作次数 ≤ k 的情况下最多能让多少个数字变成相同的值。---思路分析这是一个典型的滑动窗口 前缀和 贪心问题。核心观察· 如果要把某个区间内的数字都变成同一个值那么变成这个区间的中位数是最优的操作次数最少。· 我们需要找到最长的子数组排序后使得将其中所有数变成中位数的总操作次数 ≤ k。步骤1. 对数组排序2. 使用滑动窗口 [left, right] 表示当前考虑的区间3. 维护窗口内所有数变成中位数的代价· 中位数位置 mid (left right) / 2· 左侧部分(mid - left) * nums[mid] - sum(left, mid-1)· 右侧部分sum(mid1, right) - (right - mid) * nums[mid]4. 使用前缀和快速计算区间和5. 如果代价 k移动左边界否则更新最大长度---代码实现javaimport java.util.Arrays;class Solution {public int maxFrequencyScore(int[] nums, long k) {Arrays.sort(nums);int n nums.length;// 前缀和数组prefix[i] 表示 nums[0] 到 nums[i-1] 的和long[] prefix new long[n 1];for (int i 0; i n; i) {prefix[i 1] prefix[i] nums[i];}int maxLen 0;int left 0;for (int right 0; right n; right) {// 对于当前窗口 [left, right]计算代价int mid left (right - left) / 2;// 左侧代价(mid - left) * nums[mid] - sum(left, mid-1)long leftCost (long) nums[mid] * (mid - left) - (prefix[mid] - prefix[left]);// 右侧代价sum(mid1, right) - (right - mid) * nums[mid]long rightCost (prefix[right 1] - prefix[mid 1]) - (long) nums[mid] * (right - mid);long totalCost leftCost rightCost;if (totalCost k) {// 当前窗口满足条件更新最大长度maxLen Math.max(maxLen, right - left 1);} else {// 不满足条件移动左边界left;}}return maxLen;}}---测试示例javapublic class Main {public static void main(String[] args) {Solution solution new Solution();int[] nums1 {1, 2, 4};System.out.println(solution.maxFrequencyScore(nums1, 5)); // 输出: 3int[] nums2 {1, 4, 4, 2, 4};System.out.println(solution.maxFrequencyScore(nums2, 0)); // 输出: 3int[] nums3 {1, 1, 1, 2, 2, 2};System.out.println(solution.maxFrequencyScore(nums3, 1)); // 输出: 4}}---复杂度分析· 时间复杂度O(n log n)排序 O(n log n) 滑动窗口 O(n)· 空间复杂度O(n)前缀和数组 O(n)---关键点总结1. 排序让滑动窗口能够处理连续区间2. 中位数性质区间内所有数变成中位数的总操作数最小3. 前缀和快速计算区间和避免重复计算4. 滑动窗口动态维护满足 ≤ k 的最大窗口这个解法是经典的中位数最小操作次数问题的变种掌握了滑动窗口和中位数的关系后这类题目都可以用类似思路解决。