[leetcode 周賽 158] 1224 最大相等頻率


1224 Maximum Equal Frequency最大相等頻率

問題描述

給出一個正整數數組 nums,請你幫忙從該數組中找出能滿足下面要求的 最長 前綴,並返回其長度:

  • 前綴刪除一個 元素后,使得所剩下的每個數字的出現次數相同。

如果刪除這個元素后沒有剩余元素存在,仍可認為每個數字都具有相同的出現次數(也就是 0 次)。

  • 示例 1:

輸入:nums = [2,2,1,1,5,3,3,5]
輸出:7
解釋:對於長度為 7 的子數組 [2,2,1,1,5,3,3],如果我們從中刪去 nums[4]=5,就可以得到 [2,2,1,1,3,3],里面每個數字都出現了兩次。

  • 示例 2:

輸入:nums = [1,1,1,2,2,2,3,3,3,4,4,4,5]
輸出:13

  • 示例 3:

輸入:nums = [1,1,1,2,2,2]
輸出:5

  • 示例 4:

輸入:nums = [10,2,8,9,3,8,1,5,2,3,7,6]
輸出:8

  • 提示:
    • 2 <= nums.length <= 10^5
    • 1 <= nums[i] <= 10^5

思路

  • 讀題
    前綴: 前n個元素
    符合條件: 元素頻次都相同, 只有一個不同

找規律

四種情況:

  1. 數字有兩種分類, 第一類頻次相等, 第二類比第一類頻次多1, 並且第二類只有一個數字 --> [1,1,1,2,2,3,3]
  2. 數字有兩種分類, 第一類頻次相等, 第二類頻次為1, 並且第二類只有一個數字 --> [1,1,2,2,3]
  3. 數字只有一類, 全重復 --> [1,1,1,1]
  4. 數字只有一類, 全不重復 --> [1,2,3,4]

記錄下數字出現頻次和出現頻次的出現頻次

  • 示例: nums = [2,2,1,1,5,3,3,5]
    4_4env

代碼實現

找規律 多情況分析

class Solution {
    /**
     * 數據量最大界限
     */
    private final static int SIZE = (int) 1e5 + 50;

    public int maxEqualFreq(int[] nums) {
        // freq of number 出現數字的頻次
        int[] freqOfNum = new int[SIZE];
        // freq of number's freq 出現數字頻次的頻次
        int[] freqOfFreq = new int[SIZE];
        // maxFreq 數字出現頻次的最大值
        int maxFreq = Integer.MIN_VALUE, ans = 0;

        /*
         * 四種情況:
         *  1. 數字有兩種分類, 第一類頻次相等, 第二類比第一類頻次多1, 並且第二類只有一個數字 --> [1,1,1,2,2,3,3]
         *  2. 數字有兩種分類, 第一類頻次相等, 第二類頻次為1, 並且第二類只有一個數字 --> [1,1,2,2,3]
         *  3. 數字只有一類, 全重復   --> [1,1,1,1]
         *  4. 數字只有一類, 全不重復 --> [1,2,3,4]
         */
        for (int i = 0; i < nums.length; i++) {
            freqOfNum[nums[i]]++;
            freqOfFreq[freqOfNum[nums[i]]]++;
            maxFreq = Math.max(freqOfNum[nums[i]], maxFreq);

            // 第一種情況: 最高頻次maxFreq出現數為1, 並且次高頻次(maxFreq-1)出現數*其頻次==i
            //      --> [1,1,1,2,2,3,3] --> {maxFreq:3(1), fof[2]:3, fof[3]:1, i:6}
            boolean one = (freqOfFreq[maxFreq] == 1) && (freqOfFreq[maxFreq - 1] * (maxFreq - 1) + 1 == i + 1);
            // 第二種情況: 最高頻次maxFreq出現數*其頻次==i
            //      --> [1,1,2,2,3] --> {maxFreq:2, fof[2]:2, i=4}
            boolean two = freqOfFreq[maxFreq] * maxFreq + 1 == i + 1;
            // 第三種情況: 最高頻次maxFreq出現數==1 --> [1,1,1,1] --> {maxFreq:4, fof[4]:1}
            //  與第一種情況合並
            boolean thr = freqOfFreq[maxFreq] == 1;
            if (one || two) {
                ans = i + 1;
            }
        }

        // 第四種情況: 最高頻次maxFreq==1 --> [1,2,3,4] --> {maxFreq:1, fof[1]:4}
        boolean four = maxFreq == 1;
        if (four) {
            return nums.length;
        }

        return ans;
    }
}

參考資源

第 157 場周賽 全球排名
java題解,讓一眼就看懂的算法!算是對 @楊添倫 算法的補充
C++,O(n),考慮四種情況


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM