「Offer Sword」Interview 36:数组中的逆序对

#include<iostream>
#include<vector>
using namespace std;


int reversePairsCore(vector<int>& nums, vector<int>& copyNums, int start, int last)
{
    if(start == last)
    {
        copyNums[start] = nums[start];
        return 0;
    }
    int mid = ((last-start)>>1);
    int leftCount = <span style="color:#ff0000;"><strong>reversePairsCore(copyNums, nums, start, start+mid);</strong></span>
    int rightCount =<span style="color:#ff0000;"><strong> reversePairsCore(copyNums, nums, start+mid+1, last);</strong></span>
    int i = start+mid;
    int j = last;
    int count = 0;
    int indexCopied = last;
    while(i>=start && j>=start+mid+1)
    {
        if(nums[i] > nums[j])
        {
            count += j-start-mid;
            copyNums[indexCopied--] = nums[i--];
        }
        else copyNums[indexCopied--] = nums[j--];
    }
    while(i >= start) copyNums[indexCopied--] = nums[i--];
    while(j >= start+mid+1) copyNums[indexCopied--] = nums[j--];
    return (leftCount + rightCount + count);
}
int reversePairs(vector<int>& nums)
{
    if(nums.size() < 2) return 0;
    vector<int>copyNums(nums.begin(), nums.end());
    int count = reversePairsCore(nums, copyNums, 0, nums.size()-1);
    for(int i=0; i<copyNums.size(); ++i) cout<<copyNums[i]<<" ";
    cout<<endl;
    return count;
}



int main()
{
    int arr[] = {7,5,6,4};
    vector<int> nums(arr, arr+sizeof(arr)/sizeof(int));
    int count = reversePairs(nums);
    for(int i=0; i<nums.size(); ++i) cout<<nums[i]<<" ";
    cout<<endl;
    cout<<count<<endl;

    return 0;
}


特别需要注意的是:因为归并排序采用的是递归,因此递归的参数是关键问题。

初次编程时,没有按照红色的代码写,而是写成:

    int leftCount = reversePairsCore(nums, copyNums,  start, start+mid);
    int rightCount = reversePairsCore(nums, copyNums, start+mid+1, last);
不是正确结果。

为什么会这样?

其实递归的过程没必要过于纠结,关键在于逻辑上行不行得通,实参设得对不对。如果逻辑上行得通,实参传错了,结果就会与正确结果不同。

注意到递归的中止条件是:start==last,然后赋值给copyNums; 我们知道排序的结果会存放在copyNums里面,自然中止条件所在的函数实参应该是copyNums赋值给nums,然后根据nums存放的值进行排序,排序结果自然就存放到copyNums,参数反转了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值