微軟100題-求數組中的逆序對

求數組中的逆序對的個數:在數組a中如果a[i]>a[j].且i<j則<i,j>稱爲一個逆序數對,例如數組是7,5 ,6 ,4 則逆序對共有 7,5   7,6  7,4   5,4   6,4  五個逆序對,剛開始的時候沒有思路,看了看解答之後發現,還是採用分治的思想,類似於用歸併算法實現,

空間複雜度爲n,需要一個額外的數組來存儲,時間複雜度爲log2n(2是下標了,懶得打公式了)。具體的圖解可看一下何海濤裏面的圖示。

記錄一下我的代碼吧,

//這個程序是求數組中的逆序對的
//劍指offer一書中的36題

#include<iostream>
using namespace std;
int b[100];
int n;

int Countreversion(int a[], int begin, int end)
{
        if(end == (begin+1))
        {
                if( a[begin] > a[end])
                {
                        int t=a[begin];
                        a[begin] = a[end];
                        a[end] = t;
                        return 1;
                }
                else
                {
                        return 0;
                }
        }
        else if( begin ==end)
                return 0;
        else if( end>(begin+1))
        {
                int mid = (begin+end)/2;
                int left = Countreversion (a,begin,mid); cout << "begin is " <<begin << " mid is "<< mid <<endl;cout << "left is" << left<<endl;
                cout << "The elment in a is : ";
                for(int k=0; k<n; k++)
                        cout<<a[k]<<" ";
                cout <<endl;

                int right = Countreversion (a, mid+1, end); cout << " mid+1 is " <<mid+1 <<" end is " <<end <<endl;cout << " right is " <<right <<endl;          
               cout << "The elment in a is : ";
               for(int  k=0; k<n; k++)
                        cout <<a[k]<<" ";
                cout <<endl;
               int p=mid, q=end;
                int current =end;
                int number =left+right;
                int next_q=end; //next_q 求的是下一次判斷時q的起始位置,比如 左邊是6,7,右邊是 5,9 ,則下次從5開始,因爲7<9了,

                while(p >=begin)
                {
                        q = next_q;
                        while( q>=(mid+1) && a[p] <=a[q])
                        {
                                b[current--] = a[q];
                                q--;
                        }
                        if( q>=(mid+1) && a[p]>a[q])
                        {
                                next_q = q;
                                b[current--] = a[p];
                                number+= q-(mid+1)+1;
                                p--;
                        }
                        else if( q<(mid+1))
                        {
                                while( p>=begin)
                                {
                                        b[current--]=a[p];
                                        p--;
                                }
                        }
                        if(p<begin && q>=(mid+1))// 這部分要注意,是處理左數組已經全部都複製到臨時數組裏了,但是右數組還有剩餘
                        {//最簡單的情況比如   左數組 6 ,7 右數組 3,4
                         //臨時數組裏會是6,7,6,7 ,也就是右數組還沒放到臨時數組中,則放進去爲3,4,6,7
                         //之前程序出錯,前面的都對,唯獨忘記處理這種情況了。
                                while(q>=(mid+1))
                                {
                                        b[current--] = a[q];
                                        q--;
                                }
                        }

                }
                for(int i=begin ; i<=end; i++)
                        a[i]=b[i];
                return number;
        }
}
int main()
{
        int a[100];
        cin >>n;
        for(int i=0; i<n; i++)
        {
                cin >>a[i];
                b[i]=a[i];
        }
        for(int k=0; k<n; k++)
                 cout << " a is " <<a[k]<<" ";
        cout <<endl;
        cout << "The final result is " << Countreversion(a,0,n-1)<<endl;
        return 1;
}


提供幾組測試數據:

n=7   a: 6 7 4 3 5 1 2  結果爲17

n=7   a:1 2 3 4 5 6 7  結果爲0

n=7   a:7 6 5 4 3 2 1  結果爲21


發佈了19 篇原創文章 · 獲贊 5 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章