剑指 Offer 51. 数组中的逆序对

Posted 不吐西瓜籽

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指 Offer 51. 数组中的逆序对相关的知识,希望对你有一定的参考价值。

算法记录

LeetCode 题目:

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



说明

一、题目

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

  也就是说会出现 {(7,5), (7,6), (7,4), (5,4), (6,4)} 5 个逆序对。

二、分析

  • 如果在数组长度小的情况下,可以直接使用冒泡进行对比,因为只要发生移动,也就是说当前的元素比后面元素大而且也构成逆序对的条件。
  • 这里的长度在 5w, 单纯暴力必定会超时,这里使用归并排序来进行计算。
  • 为什么使用归并排序来进行计算呢:
  • 首先在进行递归退层时我们是知道当前的序列中数组是有序的。
  • 其次在进行数组合并时,我们只需要比较两个序列中的元素谁小就先把谁放入到临时的队列中,如果这个时候出现后面一个序列的数组的元素小于了前一个序列的元素,也就是存在前一个序列的剩余元素都大于后一个序列的当前比较元素而且下标都比此下标要小,满足逆序对的条件。
class Solution {
    public int sort(int[] nums, int start, int end) {
        if(start >= end) return 0;
        int ans = 0;
        int middle = (start + end) / 2;
        ans += sort(nums, start, middle);
        ans += sort(nums, middle + 1, end);
        ans += merge(nums, start, middle, middle + 1, end);
        return ans;
    }

    public int merge(int[] nums, int s1, int e1, int s2, int e2) {
        int ans = 0;
        List<Integer> temp = new ArrayList();
        int l1 = s1, l2 = s2;
        while(l1 <= e1 || l2 <= e2) {
            if((l2 > e2) || (l1 <= e1 && nums[l1] <= nums[l2])) {
                temp.add(nums[l1]);
                l1++;
            } else {
                temp.add(nums[l2]);
                ans += e1 - l1 + 1;
                l2++;
            }
        }
        for(int i = s1; i <= e2; i++) {
            nums[i] = temp.get(i - s1);
        }
        return ans;
    }

    public int reversePairs(int[] nums) {
        return sort(nums, 0, nums.length - 1);
    }
}

总结

熟悉归并排序的使用。

以上是关于剑指 Offer 51. 数组中的逆序对的主要内容,如果未能解决你的问题,请参考以下文章

剑指offer面试题51:数组中的逆序对

剑指 Offer 51. 数组中的逆序对

剑指offer(51)

[剑指offer]51-数组中的逆序对(归并排序)

剑指 Offer 51. 数组中的逆序对

剑指 Offer 51. 数组中的逆序对