归并排序求逆序对的个数

逆序对的定义: 如果 A[i] > A[j]  并且 i < j 那么 这就是一个逆序对。如何求一个整型数组中逆序对的个数?我们可以利用归并排序来实现。

public class Solution {
    int sum ;
    //返回一个数组的逆序个数
    public int InversePairs(int [] array) {
        sum = 0;
        mergeSort(array, 0, array.length - 1);
        return sum;
       
    }
    
    // 归并排序
    //合并 A[p..q] 与 A[q + 1, r];
    public int merge(int [] A, int p, int q, int r) {
        int i,j,k;
        int cnt = 0;
        int n1 = q - p + 1;
        int n2 = r - q;
        // 创建两个数组存储 要合并的 左右两部分
        int left[] = new int[n1 +1];
        int right[] = new int[n2 + 1];
        for(i = 0; i < n1; i++)
            left[i] = A[p + i];
        for(j = 0; j < n2; j++) {
            right[j] = A[ q + 1 + j];
        }
        
        left[n1] = Integer.MAX_VALUE;// 哨兵
        right[n2] = Integer.MAX_VALUE;//哨兵
        
        k = p;
        i = 0;
        j = 0;
        // 开始合并 
        // 我们合并的是left[0~n1] 与 right[0 ~ n2];
        // 如果 left[i] <= right[j] 那么 说明right[0 ~ j -1] 都小于 left[j];
        // 所以 小鱼left[i] 的逆序个数就是 j;
        while(k <= r) {
            // 左边 小于 邮编
            if(left[i] <= right[j]) {
                A[k++] = left[i];
                i++;
                cnt += j;
                
            }else{
                A[k++] = right[j];
                
                j++;
            }
                
        }
        return cnt;
    }
     // 归并排序
    public void mergeSort(int A[], int l, int r) {
        
        if(l < r) {
            int m = (l + r) /2;
            mergeSort(A, l,m);
            mergeSort(A, m + 1, r);
            sum +=merge(A, l, m, r);
        }
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这个问题可以使用归并排序来解决。 首先,对数组进行归并排序。在归并排序的过程中,每当两个子数组合并时,统计其中的重要逆序对个数。因为在归并排序中,左右两个子数组已经有序,所以可以使用双指针法来统计重要逆序对个数。 具体来说,假设左右两个子数组分别为A和B,且A中的元素a和B中的元素b满足a>b。此时,B中的所有元素都是a的重要逆序对,因为它们与a的大小关系满足a>b。因此,可以将B中所有元素和a合并为一个有序数组,并将其加入到归并排序的结果中。 代码如下: ``` int merge(vector<int>& nums, int left, int mid, int right) { int i = left, j = mid + 1; int cnt = 0; vector<int> temp; while (i <= mid && j <= right) { if (nums[i] > nums[j]) { cnt += mid - i + 1; // 统计重要逆序对个数 temp.push_back(nums[j++]); } else { temp.push_back(nums[i++]); } } while (i <= mid) { temp.push_back(nums[i++]); } while (j <= right) { temp.push_back(nums[j++]); } for (int k = left; k <= right; k++) { nums[k] = temp[k - left]; } return cnt; } int mergeSort(vector<int>& nums, int left, int right) { if (left >= right) { return 0; } int mid = (left + right) / 2; int cnt = mergeSort(nums, left, mid) + mergeSort(nums, mid + 1, right); cnt += merge(nums, left, mid, right); return cnt; } int countImportantInversions(vector<int>& nums) { return mergeSort(nums, 0, nums.size() - 1); } ``` 其中,merge函数用于合并两个有序数组,并统计重要逆序对个数。mergeSort函数用于归并排序。countImportantInversions函数是该算法的入口,用于计算重要逆序对个数。 时间复杂度为O(nlogn),空间复杂度为O(n)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值