[LeetCode] 1224. Maximum Equal Frequency 最大相等頻率



Given an array nums of positive integers, return the longest possible length of an array prefix of nums, such that it is possible to remove exactly one element from this prefix so that every number that has appeared in it will have the same number of occurrences.

If after removing one element there are no remaining elements, it's still considered that every appeared number has the same number of ocurrences (0).

Example 1:

Input: nums = [2,2,1,1,5,3,3,5]
Output: 7
Explanation: For the subarray [2,2,1,1,5,3,3] of length 7, if we remove nums[4]=5, we will get [2,2,1,1,3,3], so that each number will appear exactly twice.

Example 2:

Input: nums = [1,1,1,2,2,2,3,3,3,4,4,4,5]
Output: 13

Example 3:

Input: nums = [1,1,1,2,2,2]
Output: 5

Example 4:

Input: nums = [10,2,8,9,3,8,1,5,2,3,7,6]
Output: 8

Constraints:

  • 2 <= nums.length <= 105
  • 1 <= nums[i] <= 105

這道題給了一個正整數數組 nums,讓返回最長的前綴子數組的長度,使得移除一個元素后所有的數字的出現次數均相等,然后特別說明了假如移除數字后數組為空,也可以看作是所有數字出現次數為0,也是符合題意的。這樣就可以知道返回結果最小也是1,因為給定的數組不會為空,還有一點需要特別注意,也就是題目中加粗的部分,必須要刪除一個數字,不能不刪除,也不能刪除超過一個的數字。既然是跟數字出現次數有關,則肯定需要統計每個數字出現的次數(感覺像廢話),這種題目做的多了去了,用一個 HashMap 來統計每個數字出現的次數就行了。這道題的難點就在於分析在哪些情況下刪除一個數字后,剩下所有的數字的出現次數均相等,首先來說一種極端情況,就是數組中的每個數字都不相同,這樣的話刪掉任意一個數字后,剩下的所有數字還是各不相同,但同時也滿足所有數字出現的次數均相同,均為1次,這樣返回的結果就是 n-1 了。

然后再來看還有什么情況,比如移除一個單個的數字后,其余的數字出現次數均相同,且多於1次,就是例子2中的情況,如何快速判斷這種情況呢?我們不僅需要知道每個數字出現的次數,而且還需要知道出現某個次數的不同數字有多少個,即反向映射,建立頻率和具有該頻率的數字的總個數之間的映射。這樣只要知道最大的頻率是多少,同時通過上面的映射也能迅速的知道具有該頻率的數字有多少個,二者相乘得到的數字若正好等於某個前綴子數組的長度減1(因為需要刪除一個數字),則表明就是例子2的情況。統計最大頻率的好處就是,當其為1時,就知道數組中的每個數字都不相同了,就是最開始說的那種情況。再來想想還有沒有漏掉的情況,是有的,但是題目中的例子沒有給出,比如 [1, 1, 2, 2, 3, 3, 3],這種情況是說最大頻率的數字只有一個(是數字3),其余的所有數字的頻率都是最大頻率減1(數字1和2的頻率都是2),這樣的話只要去掉一個最大頻率的數字就滿足要求了,這種情況如何快速驗證呢,就是用最大頻率減1,再乘以該減1后的頻率的數字的個數加1(因為之前的最大頻率的數字減1后增加了當前頻率的數字個數),若正好等於某個前綴子數組的長度減1就行了。

分析到這,基本上這道題應該沒啥問題了吧,用兩個 HashMap,分別建立數字和其出現次數的映射,還有頻率和具有該頻率的數字的個數的映射。然后就是遍歷數組了,取出當前數字 num,還有其之前的頻率 cnt,然后將 numCnt 中的映射值自增1,並更新最大頻率 mx。由於數字 num 的頻率從 cnt 變為 cnt+1 了,所以之前的頻率 cnt 的映射個數應該自減1,為了嚴謹一些,判斷一下 cnt 的映射值是否大於0,是的話再減1。然后 cnt+1 的映射值自增1,接下里就可以判斷上面分析到的三種情況了,第一種就直接判斷 mx 是否為1,第二種用 mx 乘以 freq[mx],看是否等於i,第三種用 mx-1 乘以 feq[mx-1]+1,看是否等於i,只要滿足上述任何一種情況,結果 res 就可以更新為 i+1,參見代碼如下:


class Solution {
public:
    int maxEqualFreq(vector<int>& nums) {
        int res = 0, mx = 0, n = nums.size();
        unordered_map<int, int> numCnt;
        unordered_map<int, int> freq;
        for (int i = 0; i < n; ++i) {
            int num = nums[i], cnt = numCnt[num];
            mx = max(mx, ++numCnt[num]);
            if (freq[cnt] > 0) --freq[cnt];
            ++freq[cnt + 1];
            if (mx * freq[mx] == i || (mx - 1) * (freq[mx - 1] + 1) == i || mx == 1) {
                res = i + 1;
            }
        }
        return res;
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/1224


參考資料:

https://leetcode.com/problems/maximum-equal-frequency/

https://leetcode.com/problems/maximum-equal-frequency/discuss/403743/JavaC%2B%2BPython-Only-2-Cases%3A-Delete-it-or-not

https://leetcode.com/problems/maximum-equal-frequency/discuss/403628/Easy-Python-Solution-Concise-10-lines-Explained-O(N)


LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

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



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