LeeCode题目——数组中的逆序对

数组中的逆序对

题目描述:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对总数P,并将其P对1000000007取模的结果输出。
要求:空间复杂度为O(n),时间复杂度为O(nlogn)
示例
输入 :[1,2,3,4,5,6,7,0]
输出:7

解题思路

利用暴力方法的时间复杂度为O(n^2),显然不满足要求。
假设存在两个区间[4,3]和[1,2],那么逆序对为(4,1),(4,2),(3,1),(3,2),当两个区间变的有序时,逆序对的结果一样,这就说明区间有序和无序结果是一样的。
但是如果区间有序,当其中一个元素i与元素j构成逆序对时,元素i后面的元素都可以与元素j构成逆序对。

  • 划分:将数组划分为两个区间,并进行递归划分,直到区间的大小为1;
  • 排序:使用归并排序处理两个区间,在比较元素大小时,统计逆序对;
  • 合并:合并两个区间,并累加逆序对。

python代码实现

class Solution:
    count = 0
    #两个区间合并
    def merge(self, left, right):
        res = []
        m = len(left)
        n = len(right)
        i = 0
        j = 0
        while i<m and j<n:
            if left[i] <= right[j]:
                res.append(left[i])
                i += 1
            else:
                res.append(right[j])
                j += 1
                self.count += m-i #统计逆序对
        res.extend(left[i:])
        res.extend(right[j:])
        return res
   # 归并排序
    def mergeSort(self,array):
        n = len(array)
        #当区间为1时,开始归并
        if n<=1:
            return array,0
        mid = n//2
        left,left_n = self.mergeSort(array[:mid])
        right,right_n = self.mergeSort(array[mid:])
        res = self.merge(left,right)
        return res,left_n+right_n
        
    def reversePairs(self, nums):
        if len(nums) < 2:
            return 0
        self.mergeSort(nums)
        return self.count

java代码实现

class Solution {
    public static int count = 0;
    public void merge(int[] array,int low,int mid,int high){
        
        int[] temp = new int[high-low+1];
        int i = low;
        int j = mid+1;
        int k = 0;
        while(i<=mid && j<=high){
            if(array[i]<=array[j]){
                temp[k++] = array[i];
                i++;
            } else{
                temp[k++] = array[j];
                j++;
                count += (mid+1-i);
            }
        }
        while(i<=mid) temp[k++] = array[i++];
        while(j<=high) temp[k++] = array[j++];
        for(int l=0;l<temp.length;l++){
            array[low+l] = temp[l];
        }
    }
    public void mergeSort(int[] array,int low,int high){
        if(low<high){
            int mid = (low+high)/2;
            this.mergeSort(array,low,mid);
            this.mergeSort(array,mid+1,high);
            this.merge(array,low,mid,high);
        }
    }
    public int reversePairs(int[] nums) {
        if(nums.length<2) return 0;
        this.mergeSort(nums,0,nums.length-1);
        return count;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值