三道簡單算法題(二)


1:試着用最少的比較次數去尋找數組中的最大值和最小值。

思路一:掃描數組兩次,第一次等到最大值,第二次等到最小值。總共比較次數2N,這是大家都可以想到的。

思路二:定義兩個變量存放最大值和最小值,將數組兩兩分組,兩兩進行比較,大的和最大值進行比較,小的和最小值比較,數組兩兩比較次數是N/2,分別與最大值和最小值比較的次數為N,總共比較次數1.5N。好久沒寫算法了,於是蛋疼得想實現一下。

//1:試着用最少的比較次數去尋找數組中的最大值和最小值。 
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;
}

寫完之后,發現這太簡單了,不過癮,於是又實現了兩題,當然這三道題的思路都很早之前就看過。

2:給一個整數數組,求數組中重復出現次數大於數組總個數一半的數

按照抵消的思路,如果存在一個數出現的次數大於數組的一半,將這個數與其他不同的數進行一一抵消,最后剩下的必定就是這個數,然后再驗證這個數是否是真的出現次數超過數組的一半,實現如下,以前也實現過,但是發現這次的實現和以前的實現出入較大,這是為什么呢?

//2:給一個整數數組,求數組中重復出現次數大於數組總個數一半的數
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:給一個很大的數組,里面有兩個數只出現過一次,其他數都出現過兩次,把這兩個數找出來

按照異或運算的思路解題。假設這兩個數分別為A,B;將數組的每個元素異或運算一次,得到這兩個數的異或運算結果C,因為其他的數都是兩兩出現,異或運算的值為0,這個結果值C的二進制位中為1的位必只有A,B其中一個數有,因為異或運算就是不同的值才能得到1,相同的為0。即1&1=0;0&0=0;1&0=1。那么我們就可以隨便從結果C中取出一個二進制位為1的位與其后面的0得到一個數,若結果C的二進制位后8位為00010100,那么我們就可以得到4(二進制100),然后將數組中的每一個與4進行異或運算,這樣我們就能將數組分為兩組,A,B就被分到不同的組,其他的數被分到那個組並不用管,因為經過異或運算之后的值都為0,將兩組分別就行以后運算之后就能得到A,B的值了,其他的數都互相抵消了。

//3:給一個很大的數組,里面有兩個數只出現過一次,其他數都出現過兩次,把這兩個數找出來
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;
}

三道簡單算法題(一)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM