题目描述
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。 示例 1:
输入: [7,5,6,4]
输出: 5
解题思路
- 设置一个temp临时数组
- 当左指针大于右指针时,结束代码
- 初始化逆序对数为0,设置mid为中间值
- 先看看左边有多少对逆序对,然后看看右边有多少逆序对
- 然后去依次合并左右两个有序对数组
- 当右边的数组的长度为空或者左边的值小于右边的值,把左边值放入临时数组temp中
- 反之把右边的数组的值放入temp中,并ans+ = mid - p1 + 1;
代码
var reversePairs = function(nums) {
return countResult(nums, 0, nums.length - 1);
};
var countResult = function(nums, l, r) {
let temp = new Array(nums.length).fill(0);
if(l >= r) return 0;
let ans = 0, mid = (l + r) >> 1;
ans += countResult(nums, l, mid);
ans += countResult(nums, mid + 1, r);
let k = l, p1 = l, p2 = mid + 1;
while (p1 <= mid || p2 <= r) {
if((p2 > r) || (p1 <= mid && nums[p1] <= nums[p2])) {
temp[k++] = nums[p1++];
} else {
temp[k++] = nums[p2++];
ans += (mid - p1 + 1);
}
}
for(let i = l; i <= r; i++) nums[i] = temp[i];
return ans;
}
原因分析
- 为什么上述代码会导致运行超时呢
- 临时数组temp不能在初始化在归并排序方法内
- 改写后的代码如下
// 归并排序:
// 1.处理左边,得到左边信息
// 2.处理右边,得到右边信息
// 3.最后完成合并,得到横跨两边的信息
// 设置全局变量
let temp = [];
var reversePairs = function(nums) {
while(temp.length < nums.length) temp.push(0);
return countResult(nums, 0, nums.length - 1);
};
var countResult = function(nums, l, r) {
// let temp = new Array(nums.length).fill(0);
if(l >= r) return 0;
let ans = 0, mid = (l + r) >> 1;
ans += countResult(nums, l, mid);
ans += countResult(nums, mid + 1, r);
let k = l, p1 = l, p2 = mid + 1;
while (p1 <= mid || p2 <= r) {
if((p2 > r) || (p1 <= mid && nums[p1] <= nums[p2])) {
temp[k++] = nums[p1++];
} else {
temp[k++] = nums[p2++];
ans += (mid - p1 + 1);
}
}
for(let i = l; i <= r; i++) nums[i] = temp[i];
return ans;
}