編程之美2.3——尋找水軍(抵消法)

1.在數組中尋找出現次數超過一半的一個元素。數組

2.在數組中尋找出現次數超過1/4的三個元素。學習

【思路】測試

1)常規作法:先將數組排序,時間O(nlogn);再遍歷一次,統計每一個元素出現的次數,獲得題目要求。spa

2)時間O(n)的作法:抵消法。對於第一題,每次抵消兩個不一樣的數,剩下的數組主元素出現次數仍是超過一半。即縮小題目規模的思想。code

對於第二題,則每次抵消4個數,轉化爲規模較小的問題。blog

抵消兩個數的代碼很簡單:排序

int findOverHalf(int *ID, int N){
    int ntimes=0;
    int candi;
    for(int i=0; i<N; i++){
        if(ntimes==0){
            candi=ID[i];
            ntimes=1;
        }
        else{
            if(candi==ID[i])
                ntimes++;
            else
                ntimes--;
        }
    }
    return candi;
}

抵消四個數比較麻煩,難寫周全:it

【other code】class

struct candidate{
    int a,atimes;
    int b,btimes;
    int c,ctimes;
    void init(){
        atimes=0;
        btimes=0;
        ctimes=0;
    }
    bool istheSame(int num){
        if(a==num&&atimes!=0){atimes++; return false;}
        if(b==num&&btimes!=0){btimes++;return false;}
        if(c==num&&ctimes!=0){ctimes++;return false;}

        if(atimes==0){a=num;atimes++; return false;}
        if(btimes==0){b=num;btimes++;return false;}
        if(ctimes==0){c=num;ctimes++;return false;}
        return true;
    }
    void del(){
        atimes--;
        btimes--;
        ctimes--;
    }
}person;

candidate findOverQuarters(int *ID, int N){
    person.init();
    for(int i=0; i<N; i++){
        if(person.istheSame(ID[i]))
            person.del();
    }
    return person;
}
int main(){
    int ID[]={1,1,2,2,2,3,3,3,4,4,4};
    person=findOverQuarters(ID,11);
    cout<<person.a<<person.b<<person.c<<endl;
    system("pause");
    return 0;
}

測試運行代碼是4,2,3.date

【總結】

要學習人家代碼的封裝方法。

相關文章
相關標籤/搜索