我是靠谱客的博主 凶狠大门,最近开发中收集的这篇文章主要介绍树状数组求逆序对_算法系列之-数组中的逆序对,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

题目来源 剑指offer

01 题目描述

在数组中如果前一个数字大于后一个数字,则称为这个数字组合组成一个逆序对。输入一个数组,求所有的逆序对的总数。

如 数组 {7,5,6,4} 则它的逆序对是 (7,5),(7,6),(7,4),(5,4) ,(6,4)总共有五个。

02 解法1

类似的题目,我们的第一反应都是,固定一个数,如7,然后从后面的数5,6,4中寻找是否有小于7的数,组成逆序对。这种方式实现的时间复杂度是 O(n^2)。

03 解法2

我们在学习算法的时候,学习过归并排序。如 7,5,6,4。先将数组拆分,然后再合并。合并的过程中对比排序。

初始化reverseCount = 0;

如下图将数组拆分

4ea933626300d4a9493760c2ea7806f4.png

合并 7,5 6,4

9a62f2b7c8783dcc9e56407e94c97ea9.png

我们发现 (7,5) , (6,4)可以组成一个逆序对, reverseCount+=2;

继续下面的合并,分析 左边=5,7 右边= 4,6

383417ea2a88d30a1fded1e35c15c452.png

因为在这次合并的时候,组内已经是有序的了,所以组内右边是最大值。

对比7比,右边=4,6 的最大值6都大。所以此时我们可以计算reverseCount+=2(右面数值长度);将7放入合并数组。

cf70a6b0ad2a93de913efe19e57c1df3.png

然后判断5和6。此时6更大,将6放入合并数组。

b5d01eeda98ceffd125258ebf7da8150.png

对比 5和4,5比4大,所以可以构成逆序对, reverseCount+=1(右面剩余未合并的数组长度);

e96f27aec5b1aeae2ed2ad0185247a94.png

最后

3d637fdc4e64cb3c672e807dcf0aa11a.png

结束 输出reverseCount;

时间复杂度 nlog(n)

04 总结&代码

1.用归并排序实现

2.在归并的过程中,从大到小归并,同时判断左边数组和右边数组的逆序对,如果左边的值大于右边的值,则逆序对 += 剩余待合并的右边的值。

public static long reverseCount(int[] arrays) { if (arrays == null || arrays.length == 0) { return 0; } int[] copyArray = new int[arrays.length]; return mergeSort(arrays, copyArray, 0, arrays.length - 1);}public static int mergeSort(int[] arrays, int[] copyArray, int start, int end) { if (start == end) { return 0; } int mid = (start + end) >> 1; int leftCount = mergeSort(arrays, copyArray, start, mid); int rightCount = mergeSort(arrays, copyArray, mid + 1, end); int count = merge(arrays, copyArray, start, end, mid); return (leftCount + rightCount + count) % (1000000007);}public static int merge(int[] arrays, int[] copyArray, int start, int end, int mid) { int copyEndIndex = end; int i = mid; int j = end; int count = 0; // merge while (i >= start && j >= mid + 1) { if (arrays[i] > arrays[j]) { copyArray[copyEndIndex--] = arrays[i--]; count += j - mid;// 如果左边数组大于右边,那么逆序对数量是 j-mid 即剩余长度 } else { copyArray[copyEndIndex--] = arrays[j--]; } } while (i >= start) { copyArray[copyEndIndex--] = arrays[i--]; } while (j >= mid + 1) { copyArray[copyEndIndex--] = arrays[j--]; } while (start <= end) { arrays[start] = copyArray[start]; start++; } return count;}

最后

以上就是凶狠大门为你收集整理的树状数组求逆序对_算法系列之-数组中的逆序对的全部内容,希望文章能够帮你解决树状数组求逆序对_算法系列之-数组中的逆序对所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(32)

评论列表共有 0 条评论

立即
投稿
返回
顶部