剑指 Offer - 35 - 数组中的逆序对

发布于 2024-05-04 05:27:54 字数 2016 浏览 30 评论 0

题目

解析

经典的利用归并排序解决的问题。首先你得知道归并排序。

利用归并排序的每次 merge() 过程:

  • 因为 merge() 过程,处理的两个范围都是有序的,即 [L, mid] 有序, [mid+1, R] 有序;
  • 我们可以在这里做手脚,当两部分出现 arr[p1] > arr[p2] 的时候,结果直接可以累加 mid - p1 + 1 个,这样就可以利用归并来降低复杂度;

看结合归并的一个例子:

注意这个过程明显会修改输入的数组 array

代码:

public class Solution {

    private final int mod = 1000000007;

    public int InversePairs(int[] array) {
        if (array == null || array.length <= 1)
            return 0;
        return mergeRec(array, 0, array.length - 1);
    }

    public int mergeRec(int[] arr, int L, int R) {
        if (L == R)
            return 0;
        int mid = L + (R - L) / 2;
        return ((mergeRec(arr, L, mid) + mergeRec(arr, mid + 1, R))%mod + merge(arr, L, mid, R))%mod; // 正确
//        return ((merge(arr, L, mid, R) + mergeRec(arr, L, mid))%mod + mergeRec(arr, mid + 1, R))%mod; // 错误
    }

    // [L, mid]有序, [mid+1, R]有序
    public int merge(int[] arr, int L, int mid, int R) {
        int[] help = new int[R - L + 1];
        int k = 0, sum = 0;
        int p1 = L, p2 = mid + 1;
        while (p1 <= mid && p2 <= R) {
            if (arr[p1] <= arr[p2]) {
                help[k++] = arr[p1++];
            } else {  //arr[p1] > arr[p2], 此时 p2~R 都小于 arr[p1, mid]之间的元素,从这里求得逆序数
                sum += (mid - p1 + 1);
                sum %= mod;
                help[k++] = arr[p2++];
            }
        }
        while (p1 <= mid) help[k++] = arr[p1++];
        while (p2 <= R) help[k++] = arr[p2++];
        for (int i = 0; i < k; i++) arr[L + i] = help[i];
        return sum;
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

叹沉浮

暂无简介

文章
评论
629 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文