面试题51. 数组中的逆序对(C++)---归并排序(分治思想)解题

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

示例 1:
输入: [7,5,6,4]
输出: 5

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


——题目难度:困难


 


 
 

思路
上图来源:力扣官方

                                                           归并排序(采用分治策略)
                                              
当使用归并排序的时候,"合并"的这一过程跟逆序对的计算有关。因为每次"合并"的时候,前半部分子序列跟后半部分子序列比较的过程会和逆序对的个数有关系:

nums[j](后半部分子序列)看成比较的对象的话
然后当nums[i]>nums[j]的时候,包括nums[i]在内的 前半数组剩余的数字(也就是下标到mid为止的剩余数字) 都要比nums[j]大---因为前半数组排好序了,所以针对nums[j]来说 此刻新增的逆序对数目就是(mid-i+1)

-下面代码
 

class Solution {
public: 
	int count = 0;
    int reversePairs(vector<int>& nums) {
    	if(nums.size()==0) return 0;
		vector<int> replica(nums.size(),0);
		Merge_Sort(0,nums.size()-1,replica,nums);
		return count;
    }
    //l表示left, r表示right 
    void Merge_Sort(int l,int r,vector<int> &replica, vector<int> &nums){
    	if(l==r) return ; //分成一个元素就无需再分了
    	int mid = (l+r)/2;
    	
		Merge_Sort(l,mid,replica,nums); //"分"的部分
		Merge_Sort(mid+1,r,replica,nums); //"分"的部分 
		
		int i=l,j=mid+1,pos=l; //"治"的部分 
		while(i<=mid && j<=r)  {
		   if(nums[i]>nums[j]){
			 replica[pos++]=nums[j++];
			 count += (mid-i+1); // 将nums[j]看成比较的对象, 针对nums[j]来说 此刻新增的逆序对数目就是(mid-i+1)
		   }else{				
		 	 replica[pos++]=nums[i++];
		   }
		}
		if(i<=mid) copy(nums.begin()+i, nums.begin()+mid+1, replica.begin()+pos);
		else if(j<=r) copy(nums.begin()+j, nums.begin()+r+1, replica.begin()+pos);
		copy(replica.begin()+l, replica.begin()+r+1, nums.begin()+l); //将已经排好序的replica拷贝到nums中去 
	}
};

结果

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

重剑DS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值