三道簡單算法題(二)
1:試著用最少的比較次數(shù)去尋找數(shù)組中的最大值和最小值。
思路一:掃描數(shù)組兩次,第一次等到最大值,第二次等到最小值。總共比較次數(shù)2N,這是大家都可以想到的。
思路二:定義兩個(gè)變量存放最大值和最小值,將數(shù)組兩兩分組,兩兩進(jìn)行比較,大的和最大值進(jìn)行比較,小的和最小值比較,數(shù)組兩兩比較次數(shù)是N/2,分別與最大值和最小值比較的次數(shù)為N,總共比較次數(shù)1.5N。好久沒寫算法了,于是蛋疼得想實(shí)現(xiàn)一下。
//1:試著用最少的比較次數(shù)去尋找數(shù)組中的最大值和最小值。 void FindMaxMin(int *A,int size,int* Max,int* Min) { int i=(size & 1)?1:0; *Max=*Min=A[0]; for(;i<size;i=i+2) { if(A[i]>A[i+1]) { if(A[i]>*Max) *Max=A[i]; if(A[i+1]<*Min) *Min=A[i+1]; }else{ if(A[i+1]>*Max) *Max=A[i+1]; if(A[i]<*Min) *Min=A[i]; } } } void FindMaxMinTest(){ int A[9]={2,4,6,8,9,1,3,5,7}; int Max=0; int Min=0; FindMaxMin(A,9,&Max,&Min); cout<<Max<<endl; cout<<Min<<endl; }
寫完之后,發(fā)現(xiàn)這太簡單了,不過癮,于是又實(shí)現(xiàn)了兩題,當(dāng)然這三道題的思路都很早之前就看過。
2:給一個(gè)整數(shù)數(shù)組,求數(shù)組中重復(fù)出現(xiàn)次數(shù)大于數(shù)組總個(gè)數(shù)一半的數(shù)
按照抵消的思路,如果存在一個(gè)數(shù)出現(xiàn)的次數(shù)大于數(shù)組的一半,將這個(gè)數(shù)與其他不同的數(shù)進(jìn)行一一抵消,最后剩下的必定就是這個(gè)數(shù),然后再驗(yàn)證這個(gè)數(shù)是否是真的出現(xiàn)次數(shù)超過數(shù)組的一半,實(shí)現(xiàn)如下,以前也實(shí)現(xiàn)過,但是發(fā)現(xiàn)這次的實(shí)現(xiàn)和以前的實(shí)現(xiàn)出入較大,這是為什么呢?
//2:給一個(gè)整數(shù)數(shù)組,求數(shù)組中重復(fù)出現(xiàn)次數(shù)大于數(shù)組總個(gè)數(shù)一半的數(shù) int MoreThanHalf(int *A,int size) { int num=A[0]; int count=1; for(int i=1;i<size;i++) { if(num==A[i]) { count++; }else{ count--; if(count==0) { num=A[i]; count=1; } } } count=0; for(int i=0;i<size;i++) { if(A[i]==num) count++; } return count>(size/2)? num:-1; } void MoreThanHalfTest() { int A[9]={ 1, 1,2, 1, 2, 2, 1, 2, 2 }; cout<<MoreThanHalf( A,9); }
3:給一個(gè)很大的數(shù)組,里面有兩個(gè)數(shù)只出現(xiàn)過一次,其他數(shù)都出現(xiàn)過兩次,把這兩個(gè)數(shù)找出來
按照異或運(yùn)算的思路解題。假設(shè)這兩個(gè)數(shù)分別為A,B;將數(shù)組的每個(gè)元素異或運(yùn)算一次,得到這兩個(gè)數(shù)的異或運(yùn)算結(jié)果C,因?yàn)槠渌臄?shù)都是兩兩出現(xiàn),異或運(yùn)算的值為0,這個(gè)結(jié)果值C的二進(jìn)制位中為1的位必只有A,B其中一個(gè)數(shù)有,因?yàn)楫惢蜻\(yùn)算就是不同的值才能得到1,相同的為0。即1&1=0;0&0=0;1&0=1。那么我們就可以隨便從結(jié)果C中取出一個(gè)二進(jìn)制位為1的位與其后面的0得到一個(gè)數(shù),若結(jié)果C的二進(jìn)制位后8位為00010100,那么我們就可以得到4(二進(jìn)制100),然后將數(shù)組中的每一個(gè)與4進(jìn)行異或運(yùn)算,這樣我們就能將數(shù)組分為兩組,A,B就被分到不同的組,其他的數(shù)被分到那個(gè)組并不用管,因?yàn)榻?jīng)過異或運(yùn)算之后的值都為0,將兩組分別就行以后運(yùn)算之后就能得到A,B的值了,其他的數(shù)都互相抵消了。
//3:給一個(gè)很大的數(shù)組,里面有兩個(gè)數(shù)只出現(xiàn)過一次,其他數(shù)都出現(xiàn)過兩次,把這兩個(gè)數(shù)找出來 void FindTwoNum(int* A,int size, int* first,int* second) { int excVal=A[0]; for(int i=1;i<size;i++) { excVal^=A[i]; } int s1=1; int s2=excVal; while((s2&1)==0) { s2>>=1; s1<<=1; } *first=excVal; for(int i=0;i<size;i++) { if(s1&A[i]) *first^=A[i]; } *second=excVal^*first; } void FindTwoNumTest() { int A[12]={2,1,1,2,3,3,5,7,4,4,7,9}; int first=0,second=0; FindTwoNum(A,12,&first,&second); cout<<first<<endl; cout<<second; }
浙公網(wǎng)安備 33010602011771號(hào)