leetcode每日一题系列-最高频元素的频数

leetcode-1838-最高频元素的频数

今天搬家来晚了些,早就已经写完了,一直在跑二分的数据集+搬家,本题的数据感受真的不适合二分html

[博客连接]

菜🐔的学习之路java

掘金首页git

[题目描述]

元素的 频数 是该元素在一个数组中出现的次数。 
​
 给你一个整数数组 nums 和一个整数 k 。在一步操做中,你能够选择 nums 的一个下标,并将该下标对应元素的值增长 1 。 
​
 执行最多 k 次操做后,返回数组中最高频元素的 最大可能频数 。 
​
​
​
 示例 1: 
​
​
输入:nums = [1,2,4], k = 5
输出:3
解释:对第一个元素执行 3 次递增操做,对第二个元素执 2 次递增操做,此时 nums = [4,4,4] 。
4 是数组中最高频元素,频数是 3 。 
​
 示例 2: 
​
​
输入:nums = [1,4,8,13], k = 5
输出:2
解释:存在多种最优解决方案:
- 对第一个元素执行 3 次递增操做,此时 nums = [4,4,8,13] 。4 是数组中最高频元素,频数是 2 。
- 对第二个元素执行 4 次递增操做,此时 nums = [1,8,8,13] 。8 是数组中最高频元素,频数是 2 。
- 对第三个元素执行 5 次递增操做,此时 nums = [1,4,13,13] 。13 是数组中最高频元素,频数是 2 。
​
​
 示例 3: 
​
​
输入:nums = [3,9,6], k = 2
输出:1
​
​
​
​
 提示: 
​
​
 1 <= nums.length <= 105 
 1 <= nums[i] <= 105 
 1 <= k <= 105 
​
 Related Topics 数组 二分查找 前缀和 滑动窗口 
 👍 64 👎 0
复制代码

[题目连接]

leetcode题目连接github

[github地址]

代码连接数组

[思路介绍]

思路一:前缀和+暴力扫描+排序markdown

  • 能够思考一个问题就是咱们操做变化的元素会不会超过数组的最大元素
  • 若是咱们变大了最大元素,且最大元素是最高频次元素,那其他操做都要所以增长
  • 所以咱们能够假定咱们不须要变大最大元素* 这样就确立了一个二分范围
  • 第一个元素的元素和 和全部元素的元素和
  • 先用暴力法看一下,不走二分,直接所有遍历一次
  • 经过前缀和+k与元素值* 元素数量作比较,
  • res表示当前元素sum[i]+k >=sum[i-res-1] + (res+1) * nums[i-1]
  • 知足则取元素数量* 而后递增res知道res=i便可 最后返回res
public int maxFrequency(int[] nums, int k) {
            Arrays.sort(nums);
            int n = nums.length;
            int res = 1;
            int[] sums = new int[n + 1];
            sums[1] = nums[0];
            for (int i = 2; i <= n; i++) {
                sums[i] = sums[i - 1] + nums[i - 1];
            }
            //i表示i个元素
            for (int i = 1; i <= n; i++) {
                //至少能保证res+1个元素知足才更新
                while (res < i && sums[i] + k >= sums[i - res - 1] + (res + 1) * nums[i - 1]) {
                    res++;
                }
            }
            return res;
        }
复制代码

时间复杂度 O ( n 2 ) O(n^{2}) app

**n表示数组长度oop


思路二:思路一+二分学习

  • 其实思路一已经提到了二分只是没有实现
class Solution {
     int[] nums, sum;
        int n, k;
        public int maxFrequency(int[] _nums, int _k) {
            nums = _nums;
            k = _k;
            n = nums.length;
            Arrays.sort(nums);
            sum = new int[n + 1];
            for (int i = 1; i <= n; i++) sum[i] = sum[i - 1] + nums[i - 1];
            int l = 0, r = n;
            while (l < r) {
                int mid = l + r + 1 >> 1;
                if (check(mid)) l = mid;
                else r = mid - 1;
            }
            return r;
        }
        boolean check(int len) {
            for (int l = 0; l + len - 1 < n; l++) {
                int r = l + len - 1;
                int cur = sum[r + 1] - sum[l];
                int t = nums[r] * len;
                if (t - cur <= k) return true;
            }
            return false;
        }
    
}
复制代码

时间复杂度 O ( n l g n ) O(n*lg_{n}) spa

不过我发现,二分反倒容易TLE,感受应该是中间值的计算在这个数据集里更多

相关文章
相关标签/搜索