[剑指OFFER] 数组中的逆序对

题目描述

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
 
 
分析:利用归并排序的思想,分成2部分,每一部分按照从大到小排序,然后比较左侧的a[i]和右侧的b[j]
 
若a[i]>b[j],那么a[j]大于b[j]~b[right], 产生 right-j+1 组逆序对。
若a[j]<=b[j],不产生逆序对。
 
同时更新数组的从left到right部分,实现其从大到小排序,然后在拿排序号的数组和更大的数组进行排序,同时计算逆序组的数量。
 
class Solution {
    private:
        int merge(vector<int>& data, int left, int mid, int right)
        {
            vector<int> tmpVec;
            int cnt = 0;
            int i = left, j = mid + 1;
            // sort vecotr from big to small
            while(i <= mid && j <= right)
            {
                if(data[i] > data[j])
                {
                    cnt += (right - j + 1);
                    tmpVec.push_back(data[i]);
                    i++;
                }
                else
                {
                    tmpVec.push_back(data[j]);
                    j++;
                }

            }

            while(i <= mid)
            {
                tmpVec.push_back(data[i]);
                i++;
            }

            while(j <= right)
            {
                tmpVec.push_back(data[j]);
                j++;
            }

            //copy tmp data to original data
            for(int k = 0; k <= (right - left); k++)
            {
                data[k + left] = tmpVec[k];
            }
            return cnt;
        }
        int inversePairs(vector<int>& data, int left, int right)
        {
            if(data.size() == 0)
                return 0;
            if(left >= right)
                return 0;

            int mid = (left + right)/2;
            int cnt = 0;
            cnt += inversePairs(data, left, mid);
            cnt += inversePairs(data, mid + 1, right);
            cnt += merge(data, left, mid, right);

            return cnt;
        }
    public:
        int InversePairs(vector<int> data)
        {
            return inversePairs(data, 0, data.size() - 1);
        }
};

 

posted @ 2015-07-15 13:52  穆穆兔兔  阅读(283)  评论(0编辑  收藏  举报