給定一個長度為N的數組,找出出現次數大於n/2,n/3的數,要求時間復雜度O(n),空間復雜度O(1)


  先討論出現次數大於n/2的數字,如果這樣的數字存在,那么這個數出現的次數大於其他數出現的次數的總和。

在數組A中,我們定義兩個數據集合a1,a2。a1為出現次數大於n/2的數的集合,a2為其余數組成的集合。對於數組

A中元素a、b,假設a不等於b,那么有兩種情況,分別為:a屬於a1,b屬於a2;a屬於a2,b屬於a2。對於這兩種情況,如

果把a、b從數組A中去掉,集合a1的size依舊是大於a2的。按照這個思路,我們有如下代碼:

   int m;
    int count = 0;
    for (auto num : nums) 
   {
     // 初始的時候為1
if (0 == count) { m = num; ++count; } else {
       // 相等的話我們加一 不相等就同時去掉
if (m == num) ++count; else --count; }
  }

 

那么對於找出次數大於1/3的情況,我們最多存在兩個這樣的數字n,m。也就是說任一的n或者m與剩下的部分的比例為1:1,這就轉化為求次數大於1/2的情況了。代碼如下:

int m, n; //最多存在2個出現次數超過 1/3 的元素
    int cm, cn; //對應 m 和 n 的統計
    for (auto num : nums) {
        if (cm == 0 || num == m) {
            m = num;
            ++cm;
        }
        else if (cn == 0 || num == n) {
            n = num;
            ++cn;
        }
        else {
            --cm;
            --cn;
        }
    }
  

  if(cm > (cn+cm)/3) cout << m <<endl;
  if(cn > (cn+cm)/3) cout << n << endl;

 

可以簡單的理解為,如果從不超過1/3的那部分數據中去掉一個數字,那么n,m對應的數據集合分別要去掉一個數字,n,m對應的數據集size大於1/3的條件才不會變。

上面有一個假設是有解的,對於無解的情況,還需要額外的遍歷一次進行驗證。

 


免責聲明!

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



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