2021年02月12日 周五 天气晴 【不悲叹过去,不荒废现在,不惧怕未来】
本文目录
1. 问题简介
2. 归并排序的应用
做这道题之前要十分熟悉归并排序,这里推荐 图解排序算法(四)之归并排序,借助图解能够非常快速地理解归并排序的内涵。
熟练掌握归并排序后,再仔细看下leetcode上 superkakayong 大佬的题解,这道题的解题思路也就比较清晰了。之后就是按照思路,一步步写出代码。由思路构建代码的过程一定充满了艰辛,但这也是我们需要重点训练的,只有按照思路亲手写出代码来,才算真正掌握了方法。
下面是 superkakayong 大佬的leetcode题解代码:
class Solution {
public:
int reversePairs(vector<int>& nums) {
int len = nums.size();
if (len < 2) {
return 0; // 若不存在数对,直接 return 0
}
vector<int> helper(len);
return reversePairs(nums, 0, len - 1, helper);
}
private:
int reversePairs(vector<int>& nums, int left, int right, vector<int>& helper) {
if (left == right) {
return 0; // 递归终止条件是只剩一个元素了(即不存在数对了)
}
int mid = left + (right - left) / 2; // 此算式等同于 (left + right) / 2,是为了避免溢出
int leftPairs = reversePairs(nums, left, mid, helper); // 计算左半部分的逆序对
int rightPairs = reversePairs(nums, mid + 1, right, helper); // 计算右半部分的逆序对
if (nums[mid] <= nums[mid + 1]) {
// 此判断用于加速,即如果左右都已排好序,而且左边的最大值 <= 右边的最小值,
// 那么就不存在跨越左边和右边的逆序对了
return leftPairs + rightPairs;
}
int crossPairs = mergeAndCount(nums, left, mid, right, helper); // 计算跨越左边和右边的逆序对
return leftPairs + rightPairs + crossPairs;
}
int mergeAndCount(vector<int>& nums, int left, int mid, int right, vector<int>& helper) {
// 本函数的前提条件是:左半部分和右半部分都是已经按升序排好序了的
// 因为本函数是从左右部分都是只有一个元素的情况开始运行的(自底向上),所以是可以保证前提条件的
for (int i = left; i <= right; ++i) {
helper[i] = nums[i]; // 先填充 helper 辅助数组
}
int i = left, j = mid + 1; // i 和 j 分别是左半部分和右半部分的起点
int count = 0; // count 用来统计逆序对数量
for (int k = left; k <= right; ++k) {
if (i == mid + 1) {
// 假如 i 已经越过左边的边界,直接填充右半部分进 nums
nums[k] = helper[j];
++j;
} else if (j == right + 1) {
// 假如 j 已经越过右边的边界,直接填充左半部分进 nums
nums[k] = helper[i];
++i;
} else if (helper[i] <= helper[j]) {
// 注意健壮的归并排序这里要是 <=
// 假如左边小于等于右边,那就不是逆序对,不用修改 count
nums[k] = helper[i];
++i;
} else {
// 假如左边大于右边,是逆序对,count += 当前左边 [i, mid] 的所有元素
// 因为假如左边是 [7,8],右边是[5,6],然后 i 指向 7,j 指向 5
// 那么 5 和 7、8 都构成了逆序对,也就是此时有两对新的逆序对
// 所以可以总结出规律:count += mid - i + 1
nums[k] = helper[j];
count += mid - i + 1;
++j;
}
}
return count;
}
};
参考文献
《剑指offer 第二版》
https://www.cnblogs.com/chengxiao/p/6194356.html
https://leetcode-cn.com/problems/shu-zu-zhong-de-ni-xu-dui-lcof/solution/zi-jie-ti-ku-jian-51-kun-nan-shu-zu-zhon-eipc/