栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

剑指Offer(51)数组中的逆序对

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

剑指Offer(51)数组中的逆序对

目录

数组中的逆序对

描述

示例 1

限制

方法:归并排序


数组中的逆序对

描述

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

示例 1

输入

[7,5,6,4]

输出

5

限制

0 <= 数组长度 <= 50000

方法:归并排序

归并排序想必大家都比较熟悉,在归并的过程,就是比较子数组元素的大小,当左边数组当前元素大于右边数组当前元素时,我们认为左边的当前元素至末尾元素与右边的当前元素构成了若干个逆序对。

合并统计逆序对的步骤如下:

  • 将数组nums[low,high]拷贝到temp数组中
  • 循环合并,设置双指针i,j分别指向左右子数组的首元素(i=low,j=mid+1),其中mid=(low+high)/2
    • 当i=mid+1时,代表左子数组已经合并完,此时仅需要添加右边数组元素temp[j++]
    • 当j=high+1时,代表右子数组已经合并完,此时仅需要添加左边数组元素temp[i++]
    • 否则左右数组均未合并完,需要比较temp[i]与temp[j]的大小
      • 当temp[i]<=temp[j]时,添加左边数组元素temp[i++]
      • 当temp[i]>temp[j]时,添加右边数组元素temp[j++];此时构成mid-i+1个逆序对,累加
class Solution {
    int[] nums, temp;
    public int reversePairs(int[] nums) {
        this.nums = nums;
        temp = new int[nums.length];
        return mergeSort(0, nums.length - 1);
    }
    private int mergeSort(int low, int high) {
        if (low >= high) return 0;
        int mid = (low + high) / 2;
        int res = mergeSort(low, mid) + mergeSort(mid + 1, high);//递归划分数组
        for (int i = low; i <= high; i++) {
            temp[i] = nums[i];//复制nums[low,high]的数组到temp中
        }

        int i = low, j = mid + 1;
        for (int k = low; k <= high; k++) {
            if (i == mid + 1) {
                nums[k] = temp[j++];//左边数组合并完了,添加右边数组的元素
            }
            else if (j == high + 1 || temp[i] <= temp[j]) {
                nums[k] = temp[i++];//右边数组合并完了或者左边元素小于右边,添加左边数组的元素
            }
            else {//两边元素都没合并完,且左边元素大于右边,此时构成mid-i+1个逆序对
                nums[k] = temp[j++];
                res += mid - i + 1;
            }
        }
        return res;
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/325023.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号