day39:数组中的逆序对(归并排序)

问题描述:
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
示例 1:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof

注意该问题是逆序数对个数之和,如果是从小到大的数列,那么逆序数对总数为0,如果逆序数对是从大到小排列,那么逆序数对总数会是很高计算。例如【5,4,3,2,1】逆序数对总和为4+ 3 +2 + 1 =10。
问题求解使用到了归并排序,在排序整个数组的过程中将逆序的数对个数进行求解,使用递归进行归并排序,将整个数组分成两部分,分别用 i , j 指向这两个数组的起始位置,比较 nums[i]和nums[j]的大小 ,需要将小的那一个放入temp数组,如果nums[i]>nums[j],此时就意味着出现了逆序数对,注意理解的时候mid-i+1这个计算结果是在有序数组的基础上计算的,只有有序,数组中的元素才会放入到temp中,由于该过程涉及到递归,所以理解的时候要自下至上理解。如果数组有剩余部分没有遍历到,那么剩余的数组要拷贝到原始数组中。

class Solution {
public:
    int merge(vector<int>&nums,int l,int r)
    {
        if(l>=r) return 0;
        int mid=l+r >> 1;
        int res=merge(nums,l,mid)+merge(nums,mid+1,r);
        int i=l,j=mid+1;
        vector<int> temp;
        while(i<=mid&&j<=r)
        {
            if(nums[i]<=nums[j]) temp.push_back(nums[i++]);
            else
            {
                temp.push_back(nums[j++]);
                res+=mid-i+1;
            }
        }
        while(i<=mid) temp.push_back(nums[i++]);
        while(j<=r) temp.push_back(nums[j++]);
        i=l;
        for(auto x:temp) nums[i++]=x;
        return res;
    }
    int inversePairs(vector<int>& nums) {
        return merge(nums,0,nums.size()-1);
    }
};

你可能感兴趣的:(剑指offer)