先討論出現次數大於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的條件才不會變。
上面有一個假設是有解的,對於無解的情況,還需要額外的遍歷一次進行驗證。