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

153 阅读1分钟

题目来源:[leetcode 剑指 Offer 51. 数组中的逆序对

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

示例 1:

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

分析

  • 定义一个res存入逆序对个数
  • 判断当前值与之后所有的值进行比较,大于则 res++

代码实现

/**
 * @param {number[]} nums
 * @return {number}
 */
var reversePairs = function(nums) {
    let res = 0;
    const length = nums.length;
    for (let i = 0; i < length; ++i) {
        for (let j = i + 1; j < length; ++j) {
            if(nums[i] > nums[j]) res++
        }
    }
    return res;
};

分析2

  • 利用有序数组的逆序对求法即可优化运行时间
  • 利用归并排序,当right[j]小于left[i]的时候就说明i至leftLen都是逆序对(leftLen - i)

代码实现2

/**
 * @param {number[]} nums
 * @return {number}
 */
var reversePairs = function(nums) {
    let sum = 0;
    mergeSort(nums);
    function mergeSort (nums) {
        if(nums.length < 2) return nums;
        const mid = Math.floor(nums.length/2);
        let left = nums.slice(0,mid);
        let right = nums.slice(mid);
        return merge(mergeSort(left), mergeSort(right));
    }
    function merge(left, right) {
        let res = [];
        let leftLen = left.length;
        let rightLen = right.length;
        let len = leftLen + rightLen;
        let i = 0;
        let j = 0;
        for(let index = 0; index < len; index ++) {
            if(i >= leftLen) res[index] = right[j ++];
            else if (j >= rightLen) res[index] = left[i ++];
            else if (left[i] <= right[j]) res[index] = left[i ++];
            else {
                res[index] = right[j ++];
                sum += leftLen - i;
            }
        }
        return res;
    }
    return sum;
};

分析3

  • 代码实现2中由于多次定义数组,数组在创建与销毁的时候都会有时间的损耗

代码实现3

var reversePairs = function (nums) {
  let res = 0;
  let temp = [];
  function reverse(nums, left, right) {
    if (left >= right) {
      return 0;
    }
    let mid = left + Math.floor((right - left) / 2);
    reverse(nums, left, mid);
    reverse(nums, mid + 1, right);
    merge(left, right, mid, nums);
  }

  function merge(left, right, mid, nums) {
    for (let x = left; x <= right; x++) {
      temp[x] = nums[x];
    }
    let i = left,
      j = mid + 1;
    for (let k = left; k <= right; k++) {
      if (i > mid) {
        nums[k] = temp[j++];
      } else if (j > right) {
        nums[k] = temp[i++];
      } else if (temp[i] <= temp[j]) {
        nums[k] = temp[i++];
      } else {
        nums[k] = temp[j++];
        res = res + mid - i + 1;
      }
    }
  }
  reverse(nums, 0, nums.length - 1);
  return res;
};