【劍指offer】面試題36:數組中的逆序對


題目:

在數組中的兩個數字,如果前面一個數字大於后面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個數組中的逆序對的總數。

思路:

歸並排序的合並過程。主要是考慮合並兩個有序序列時,計算逆序對數。

對於兩個升序序列,設置兩個下標:兩個有序序列的末尾。每次比較兩個末尾值,如果前末尾大於后末尾值,則有”后序列當前長度“個逆序對;否則不構成逆序對。然后把較大值拷貝到輔助數組的末尾,即最終要將兩個有序序列合並到輔助數組並有序。

這樣,每次在合並前,先遞歸地處理左半段、右半段,則左、右半段有序,且左右半段的逆序對數可得到,再計算左右半段合並時逆序對的個數。

總個數=左個數+右個數+左右合並時的個數

注意:

注意InversePairsCore形參的順序是(data,copy),而遞歸調用時實參是(copy,data)。

要明白遞歸函數InversePairsCore的作用就行了,它是對data的左右半段進行合並,復制到輔助數組copy中有序。

最后,data和copy兩個數組都是有序的。

代碼:

class Solution {
public:
    int InversePairs(vector<int> data) {
        if(data.size()<=1)  return 0;
        
        vector<int>  copy(data);
        return InversePairsCore(data,copy,0,data.size()-1);
    }
private:
    int InversePairsCore(vector<int> &data,vector<int> &copy, int begin, int end)
    {//合並data的兩半段到輔助數組copy中有序
        if(begin==end)
        {
            copy[end]=data[end];
            return 0;
        }
        else
        {
            int mid=begin+(end-begin)/2;
            
            int left=InversePairsCore(copy,data,begin,mid);//使data的左半段有序 
            int right=InversePairsCore(copy,data,mid+1,end);//使data的右半段有序 
            
            int cnt=0;
            int cpIndex=end;
            int pre=mid;
            int post=end;
            //合並兩個有序段,到copy數組 
            while(pre>=begin && post>=mid+1)
            {
                if(data[pre]>data[post])//每次比較的是兩個有序序列
                {
                    cnt=cnt+(post-mid-1+1);
                    copy[cpIndex--]=data[pre];
                    pre--;
                }
                else
                {
                    copy[cpIndex--]=data[post];
                    post--;
                }
            }
            
            for(;pre>=begin;--pre)
                copy[cpIndex--]=data[pre];
            for(;post>=mid+1;--post)
                copy[cpIndex--]=data[post];
            
            return left+right+cnt;
        }
    }
};

 


免責聲明!

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



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