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,感受應該是中間值的計算在這個數據集裏更多

相關文章
相關標籤/搜索