leetcode-剑指 Offer 51. 数组中的逆序对

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

示例 1:

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

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

解题思路:
首先想到的是暴力的方式,遍历数组,然后再从每一个数字后一位开始遍历,查找所有比他小的数字,计数++。但是0 <= 数组长度 <= 50000,时间复杂度为O(n*n),会超时,所以此方法不可行。
然后想到了二分降低时间复杂度,但是这道题提并不适合,然后联想到了分治,但是实现代码就有点困难啦 。。。。。
在这里插入图片描述
向高人请教,据说本题就是归并排序(小白目前还是不太明白归并代码),只不过引入了一个ans记录逆序对的个数。

分治算法将原问题分解成小规模的问题,然后根据子问题的结果构造出原问题的答案。有点类似动态规划,所以运用分治算法也需要满足一些条件:原问题的答案应该可以通过子问题结果计算。典型的分治算法就是归并排序,核心逻辑如下:

 void Sort(vector<int>&nums,int left,int right)  
    {
        if(left>=right) return ;
        int mid=left+(right-left)/2;
        Sort(nums,left,mid);           //分
        Sort(nums,mid+1,right);
        Merge(nums,left,mid,right);    //治
    }

本题代码:

class Solution {
    int ans=0;
    void Sort(vector<int>&nums,int left,int right)  //‘分’着处理每一个区间
    {
        if(left>=right) return ;
        int mid=left+(right-left)/2;
        Sort(nums,left,mid);
        Sort(nums,mid+1,right);
        Merge(nums,left,mid,right);   
    }
    void Merge(vector<int> &nums,int left,int mid,int right)   //将区间合并
    {
        int tmp[nums.size()];
        int i=left,j=mid+1,k=left;
        while(i<=mid&&j<=right)
        {
            if(nums[i]<=nums[j])
            tmp[k++]=nums[i++];
            else                   //前面的元素大于后面的 才满足逆序对,需要计数
            {
                tmp[k++]=nums[j++];
                ans+=mid-i+1;
            }
        }
        while(i<=mid) tmp[k++]=nums[i++];
        while(j<=right) tmp[k++]=nums[j++];
     for(int i=left;i<=right;i++)  //合并的区间就是从left-right,所以拷贝的也是该区间
     nums[i]=tmp[i];
    }
public:
    int reversePairs(vector<int>& nums) {
        ans=0;
        Sort(nums,0,nums.size()-1);
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值