[路飞]_剑指 Offer 51. 数组中的逆序对

89 阅读1分钟

题目路径

题目描述

在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。 示例 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;
}

1645706227(1).png

原因分析

  • 为什么上述代码会导致运行超时呢
  • 临时数组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;
}

1646186714(1).png