力扣链接:leetcode.cn/problems/re…
原理
- 思考一个问题在大范围上的答案是否等于:左部分答案 + 右部分答案 + 跨左右产生的答案
- 计算 “跨左右产生的答案” 时,若加上左、右各自有序这个设定,会不会获得计算的便利性
- 以上两点都成立,则大概率可以使用归并分治解决
代码
class Solution {
public static int MAXN = 50001;
public static int[] help = new int[MAXN];
public int reversePairs(int[] nums) {
return counts(nums, 0, nums.length - 1);
}
public int counts(int[] nums, int l, int r) {
if (l == r) {
return 0;
}
int m = (l + r) / 2;
return counts(nums, l, m) + counts(nums, m + 1, r) + merge(nums, l, m, r);
}
public int merge(int[] nums, int l, int m, int r) {
int ans = 0;
for (int i = l, j = m + 1; i <= m; i++) {
while (j <= r && (long) nums[i] > (long) 2 * nums[j]) {
j++;
}
ans += j - (m + 1);
}
int i = l;
int a = l;
int b = m + 1;
while (a <= m && b <= r) {
help[i++] = nums[a] <= nums[b] ? nums[a++] : nums[b++];
}
while (a <= m) {
help[i++] = nums[a++];
}
while (b <= r) {
help[i++] = nums[b++];
}
for (i = l; i <= r; i++) {
nums[i] = help[i];
}
return ans;
}
}