尋找大小為n的陣列中出現次數超過n/2的那個數
阿新 • • 發佈:2019-01-06
問題描述: 在一個大小為n的陣列中,其中有一個數出現的次數超過n/2,求出這個數。這題看似很簡單,但是找到最優解不容易,一般情況我們首先想到最笨的方法,每選一個數,遍歷一次陣列,複雜度O(N^2),或者先排序再找那個數,複雜度一般為O(NlgN),或者用hash,時間複雜度O(N),空間複雜度需要看輸入的資料規模,空間複雜度O(N)。所以這些都不是最優解,我們先分析一下這個題目,設該數出現的次數為x,則x滿足,n/2+1<= x <=n;所以我們可以想到如果該數和其餘的數全部相抵消的話,至少還剩1個,我們從前往後遍歷,設key為第一個數,key出現的次數為ntime,初始化為1,代表key出現了一次,從前往後,如果某個數不等於key,則他倆抵消,key的出現次數減一,如果等於key,則key的出現次數加1,如果key的出現次數變成了0,則說明key已經用完了,所以需要重新初始化key為另一個數,再重複以上步驟,因為一定有一個數大於n/2,所以遍歷到最後剩下的那個數,就是要求的數。
#include <iostream> #include <vector> using namespace std; /*在大小為n的陣列中尋找次數超過n/2的數*/ int find_data(vector<int> &arry) { int ntime = 0; //表示其中某一個數出現的次數 int result; for(unsigned int i = 0; i < arry.size(); i++) { if(ntime == 0) { //在i前面的數全部刪除完,或者起始的時候,將arry[i]放入結果 result = arry[i]; ntime = 1; //arry[i]出現的次數為1; } else { //如果前面有數,就說明result還沒抵消完 if(result == arry[i]) //如果相等result出現的次數+1 ntime++; else ntime--; /*如果此時的arry[i]不等於result,則它們兩個抵消,result的次數減一,由與那個數大於n/2所以它抵消不完,ntime最小為1 也就是說這個數出現的次數是大於等於n/2+1*/ } } return result; } int main() { vector<int> arry; int n; cin>>n; for(int i = 0; i < n; i++) { int d; cin>>d; arry.push_back(d); } int result = find_data(arry); cout<<result; return 0; }