数组中的逆序对 归并排序

题目

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。

示例 1:

输入 : [7,5,6,4]
输出 : 5

限制: 0 <= 数组长度 <= 50000

思路

听讲解后自己的理解

采用归并排序的方法来解:
归并排序就是将一个数组,二二分,直到分不下去了,再往回有序合并。

逆序对的判断在归并排序中的归并中:
左:1 3 5 7 | 右: 2 4 6 8

总:
1 2(此时有三对逆序对(3,2)(5,2)(7,2))
3 4 (此时有两对逆序对(5,4)(7,4))
5 6 (此时有一对逆序对(7,6))
7 8

当把右边的数往上放时,左边还剩几个,就有几个逆序对

举例:
1 3 7 5 4 2 6 8

1 3 7 5 | 4 2 6 8

1 3 | 7 5 | 4 2 | 6 8

->

1 3 | 5 7 | 2 4 | 6 8 这层逆序对为2个 (7,5)(4,2)

1 3 5 7 | 2 4 6 8 这层逆序对为 0个

1 2 3 4 5 6 7 8 这层逆序对为 6个

class Solution {
public:
    int reversePairs(vector<int>& nums) {  
        int len = nums.size(); 
        if(len<2) return 0; //如果小于2,也根本不会有逆序对出现
        int temp[len]; //避免每次都申请数组,占空间 
        return mergeSort(nums,0,len-1,temp);
    }
int merge(vector<int>& nums,int left,int mid,int right,int temp[]){
	
	for(int i=left;i<=right;i++){  //将原数组复制给temp 
		temp[i]=nums[i];
	}
	
	int i=left,j=mid+1;
	int sum=0;
	for (int k = left; k <= right; k++) {
        if (i == mid+1) { //左边都归并完了 
            nums[k] = temp[j++];
        } else if (j == right + 1) { // 右边都归并完了 
            nums[k] = temp[i++];
        } else if (temp[i] <= temp[j]) { //左边小 
            nums[k] = temp[i++];
        } else { // 右边小 
            nums[k] = temp[j++];
            sum += (mid - i + 1);
        }
	}
	return sum;
}

int mergeSort(vector<int>& nums,int left,int right,int temp[]){
	if(left<right){
		int mid = left+(right-left)/2;
		int l = mergeSort(nums,left,mid,temp);
		int r = mergeSort(nums,mid+1,right,temp);
		
		if(nums[mid]<=nums[mid+1]){//如果左右两个数组自动有序,就不用再合并了 
			return l+r;
		}
		
		int m = merge(nums,left,mid,right,temp);
		return l+r+m;
	}
	return 0;
} 
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数组对是指在一个数组,如果前面的数比后面的数大,则这两个数构成一个对。例如,[2, 4, 1, 3, 5],(2, 1)、(4, 1)和(4, 3)都是对。 以下是使用Python实现数组对的代码: ```python def merge(nums, left, mid, right): # 合并两个有数组,并计算对数 i = left j = mid + 1 temp = [] count = 0 while i <= mid and j <= right: if nums[i] <= nums[j]: temp.append(nums[i]) i += 1 else: temp.append(nums[j]) j += 1 count += (mid - i + 1) # 计算对数 while i <= mid: temp.append(nums[i]) i += 1 while j <= right: temp.append(nums[j]) j += 1 nums[left:right + 1] = temp return count def merge_sort(nums, left, right): # 归并排序,并返回对数 if left >= right: return 0 mid = (left + right) // 2 count = merge_sort(nums, left, mid) + merge_sort(nums, mid + 1, right) + merge(nums, left, mid, right) return count def reverse_pairs(nums): # 数组对 if not nums: return 0 return merge_sort(nums, 0, len(nums) - 1) ``` 这里我们使用归并排序来对数组进行排序,并在合并两个有数组时计算对数。具体实现时,我们先将数组分成两个子数组,然后分别对两个子数组进行归并排序,并计算两个子数组对数。然后再将两个有数组合并成一个有数组,并在合并过程计算对数。最后将得到的对数相加,就是整个数组对数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值