牛客:BM20 数组中的逆序对

题目描述
参考:https://blog.csdn.net/qq_38984851/article/details/83242429

思路

具体思路参考文中引用博客,其核心在于:每次归并之后的合并操作时进行处理,假设目前数组情形如下:
在这里插入图片描述
i指向6,j指向2,此时由于[l, m]和[m+1, r]都是有序的,所以此时[i…m]的所有元素和[j]都组成逆序对,具体个数即为m-i+1个,如果需要保存具体数对,只需将[i…m]的元素和[j]位置的元素组合即可!

代码

class Solution{
    public:
        long sum = 0;
        vector<vector<int>> pairs;
        void merge(vector<int> &vec, int l, int m, int r){
            vector<int> temp(r - l + 1, 0);
            int i = l, j = m + 1, k = 0;
            while(i <= m && j <= r){
                if(vec[i] > vec[j]){ //逆序对形成条
                    sum += m - i + 1; 
                    //在此处保存逆序对, 因为在此处vec[i] > vec[j]则可以说明vec[i...m]均大于vec[j],它们都是逆序对,所以才会出现个数为m-i+1
                    int jj = i;
                    while(jj <= m){
                        pairs.push_back(vector<int>({vec[jj++], vec[j]}));
                    }
                    temp[k++] = vec[j++];
                }else{
                    temp[k++] = vec[i++];
                }
            }
            while(i <= m){
                temp[k++] = vec[i++];
            }
            while(j <= r){
                temp[k++] = vec[j++];
            }
            k = 0;
            while(l <= r){
                vec[l++] = temp[k++];
            }
        }
        void mergeSort(vector<int> &vec, int l, int r){
            if(l < r){
                int mid = (l + r) >> 1;
                mergeSort(vec, l, mid);
                mergeSort(vec, mid + 1, r);
                merge(vec, l, mid, r);
            }
        }
        //求所有逆序对
        int InversePairs(vector<int> data){
            
            int l = 0, r = vec.size() - 1;
            mergeSort(data, l, r);

            // 打印具体的逆序对
            for(auto each : pairs){
                cout << "(" << each.front() << ", " << each.back() <<")"<<endl;
            }
            return sum % 1000000007;
        }
};

merge中的语句还可以简练,因为temp临时变量存在的目的是将vec中的[l…r]元素进行,有序化,那么可不可以在原地进行,进而去掉temp。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值