LeetCode 面试题51 数组中的逆序对(线段树+树状数组+离散化)
题目链接:数组中的逆序对
在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数。
示例 1:
输入: [7,5,6,4]
输出: 5
限制:
0 <= 数组长度 <= 50000
思路
逆序数的定义,题目已经给出。我们的核心诉求就是,对于每一项nums[i]
,求出在这个数之前,比它大的数的个数,累加起来就是答案。我们考虑如何解决这个问题。
由于只给出了数字的数量,没有给出数字的大小范围,所以先用离散化处理一下,保证所有数的区间都在[1,50000]
内。
方法1:线段树
首先此题可以用一个线段树来维护,线段树的功能是区间求和。依次遍历数组,先求出当前线段树中,大于当前遍历的nums[i]
的数的个数,然后再把当前的数更新到线段树上去(为了保证线段树上的数都是遍历的数之前的),让树上的这个点加一,然后累加起来就是答案。
方法2:树状数组
顺着这个思路,我们可以同样考虑一下用树状数组来实现,离散化不用说。首先,要知道树状数组的功能是啥,功能是:单点更新,可以求出[1,n]
的和。那么这个性质如何在逆序数中使用呢?考虑,数字的数量是固定的,对于当前遍历到的nums[i]
,可以求出[1,num[i]]
的和,代表比nums[i]小的数有多少个
,那么i-sum(1,nums[i])
就求出了它之前比它大的有多少个。同样也是边遍历边更新。
代码
线段树:
|
|
树状数组:
|
|
最后修改于 2020-04-24
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。