小鑫的算法之路:leetcodeOffer051 数组中的逆序对

题目

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

解法1:暴力求解

如果需要求出数组中的逆序对的总数,需要对数组进行双重遍历,找出数组中所有的逆序对。代码如下:

class Solution {
public:
    int reversePairs(vector<int>& nums) {
        int result = 0;
        for (size_t i = 0; i < nums.size(); ++i) {
            for (size_t j = i + 1; j < nums.size(); ++j) {
                if (nums[i] > nums[j]) {
                    ++result;
                }
            }
        }
        return result;
    }
};

由于时间复杂度为O(n^2),因此执行结果超出时间限制。

在这里插入图片描述

解法2:归并排序

由于解法1的时间复杂度为O(n^2),那么能不能想办法将时间复杂度降低为O(nlogn)呢?此时可以采用归并排序进行处理,在进行归并处理时,可以求出某一个区间内的逆序对个数,并且针对该区间进行排序后不影响整体的逆序对求解。当最终完成排序后,可求出整个区间的逆序对个数。

代码如下:

class Solution {
public:
    int reversePairs(vector<int>& nums) 
    {
        buffer_.resize(nums.size());
        sort(nums, 0, static_cast<std::ptrdiff_t>(nums.size()) - 1);
        return pairs;
    }

private:
    void sort(vector<int>& nums, ptrdiff_t left, ptrdiff_t right)
    {
        if (left >= right) {
            return;
        }

        ptrdiff_t mid = left + (right - left) / 2;
        sort(nums, left, mid);
        sort(nums, mid + 1, right);

        if (nums[mid] > nums[mid + 1]) {
            merge(nums, left, mid, right);
        }
    }

    void merge(vector<int>& nums, ptrdiff_t left, ptrdiff_t mid, ptrdiff_t right)
    {
        copy(nums.begin() + left, nums.begin() + right + 1, buffer_.begin() + left);

        ptrdiff_t i = left;
        ptrdiff_t j = mid + 1;
        for (ptrdiff_t index = left; index <= right; ++index) {
            if (i > mid) {  // 左区间已经遍历完,只需处理右区间数据即可
                nums[index] = buffer_[j];
                ++j;
            } else if (j > right) {  // 右区间已经遍历完,只需处理左区间数据即可
                nums[index] = buffer_[i];
                ++i;
            } else if (buffer_[i] > buffer_[j]) {
                // 若左区间中buffer_[i] > buffer_[j], 那么buffer_中[i, mid]的值均大于buffer_[j], 逆序对个数为(mid - i + 1)
                pairs += (mid - i + 1);
                nums[index] = buffer_[j];
                ++j;
            } else {
                nums[index] = buffer_[i];
                ++i;
            }
        }
    }

private:
    std::vector<int> buffer_;
    int pairs = 0;
};

时间复杂度降低为O(nlogn),空间复杂度为O(n),执行结果如下:

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值