問題:
長度為n的數組,有一個數重復出現了n/2+1次,找出這個數;
解決:
比較直接的思路是遍歷每個元素,讓其與剩下其他元素比較,相等一次計數器sum++,直到sum=n/2+1為止;
#include <stdio.h> #include <stdlib.h> #include <assert.h> int fun(int inp[],int size) { assert(inp!=NULL && size>1); int i=0,j=0; for(;i<size-1;i++){ int sum = 1; for(j=i+1;j<size;j++){ if(inp[i]==inp[j]) sum++; } if(size/2+1 == sum) return inp[i]; } return -1; } int main(){ int input[]={1,2,5,2,1,8,2,2,2,2}; int ret = fun(input,10); printf("result = %d\n",ret); return 0; }
結果如下:
[root@admin Desktop]# ./a.out result = 2 [root@admin Desktop]#
方法2:
有n/2+1個重復的,那我們每次從數組中提取出來一對不同的數,到最后數組中剩余的,就只能是重復的數了;
比如{1,3,1,2,1};
依次提取出1/3 , 1/2,剩余的就是1;
方案:
1.掃描一遍數組,找到不相同兩個數,都置為-1;
2.最后剩下的,全都是重復數字;
#include <stdlib.h> #include <stdio.h> #include <assert.h> int fun(int inp[],int size) { assert(inp != NULL && size>2); int i=0,j=0; for(;i<size-1;i++){//外循環,保證每個數都被遍歷到 printf("i==:%d\n",i); if(-1 == inp[i]) continue;//外循環遇到-1時,證明該數被選中並剔除過 else{ printf("in else ==:\n"); for(j=i+1;j<size;j++){ //內循環,從i往后尋找與inp[i]不同的且不為-1的元素; if(inp[i] != inp[j] && -1 != inp[j]){ printf("j==:%d\n",j); inp[i]=inp[j]=-1;//找到后都置為-1 break; } if(size-1 == j) return inp[i];//如果j走到頭都沒找到,證明剩下的都與inp[i]重復 } } } return -1;//失敗,返回-1 } int main() { int input[] = {1,2,3,1,2,1,1,6,1,1}; int ret = fun(input,10); printf("the number is:%d\n",ret); return 0; }
結果:
[root@admin Desktop]# ./a.out i==:0 in else ==: j==:1 i==:1 i==:2 in else ==: j==:3 i==:3 i==:4 in else ==: j==:5 i==:5 i==:6 in else ==: j==:7 i==:7 i==:8 in else ==: the number is:1 [root@admin Desktop]#
方法3:
這個方法不是我想到的,感覺思路極其巧妙,掃描一遍即可,且復雜度只有0(n),上面兩個算法復雜度都為O(n
2);
方案:充分利用出現次數超過一半這個特點,使用兩個變量candidate和vote,分別代表候選人和票數,遍歷數組按如下方式投票和更換候選人:
1.若當前數的值與候選人candidate一樣,則把候選人的票數加1;
2.若當前數與候選人不一樣,則把它的票數減1,如果減掉后票數小於0,則把候選人踢掉,用當前數作為新的候選人;
3.最后剩下的候選人就是出現次數超過一半的數。
算法的正確性證明: 數組中,數值相同的數都會投贊成票,數值不同的都會投反對票,有一個數出現的次數超過一半,其它數得到的反對票必然大於一半,所以其它數中,任何一個得票都會小於0,遭到淘汰。剩下來的只能是超過一半的那個數。
#include <stdlib.h> #include <stdio.h> #include <assert.h> int fun(int inp[],int size) { assert(inp != NULL && size>2); int i=0,candidate=inp[0],vote=0; for(;i<size;i++){ printf("i = %d; candidate is:%d; vote=%d\n",i,candidate,vote); if(inp[i] == candidate) vote++; else{ vote--; if(vote < 0){ candidate = inp[i]; vote = 1; } } } return candidate; } int main() { int input[] = {1,2,3,1,2,1,1,6,1,1}; int ret = fun(input,10); printf("the number is:%d\n",ret); return 0; }
結果:
[root@admin Desktop]# ./a.out i = 0; candidate is:1; vote=0 i = 1; candidate is:1; vote=1 i = 2; candidate is:1; vote=0 i = 3; candidate is:3; vote=1 i = 4; candidate is:3; vote=0 i = 5; candidate is:2; vote=1 i = 6; candidate is:2; vote=0 i = 7; candidate is:1; vote=1 i = 8; candidate is:1; vote=0 i = 9; candidate is:1; vote=1 the number is:1 [root@admin Desktop]#
