Given an array nums
, we call (i, j)
an important reverse pair if i < j
and nums[i] > 2*nums[j]
.
You need to return the number of important reverse pairs in the given array.
Example1:
Input: [1,3,2,3,1]
Output: 2
Example2:
Input: [2,4,3,5,1]
Output: 3
Note:
- The length of the given array will not exceed 50,000.
- All the numbers in the input array are in the range of 32-bit integer.
Solution: Conquer dive + Merge Sort
- 分治的方法:
- eg:
1,3,3,1
, 将序列分成左右两段,分别求其reverse pair
的数,left == 0, right == 1
; - 在求左右数的时候,已经分别对其用
merge sort
排序变为 ==>1,3, 1,3
- 再对当前list求其
reverse pair
的数: 只需要从左到右扫描一遍即可。
left = start, right = middle
- eg:
for (int left = start; left < middle; left ++) {
while (right < end && (long)nums [left] > (long) 2 * nums [right]) {
right ++;
}
count += right - middle;
}
- 每次对一个sublist求完
reverse pair
的数, 都要用merge sort
对当前sublist进行排序。这样就可以让上一层求reverse pair
的数时,只需要从左到右扫描一遍,就可以得到reverse pair
的数。
class Solution {
public int reversePairs(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
int[] copiedNums = new int[nums.length];
return reversePairsHelper (nums, copiedNums, 0, nums.length);
}
private int reversePairsHelper (int[] nums, int[] copiedNums, int start, int end) {
if (start + 1 == end) {
return 0;
}
int middle = start + (end - start) / 2;
int count = reversePairsHelper (nums, copiedNums, start, middle) + reversePairsHelper (nums, copiedNums, middle, end);
int right = middle;
for (int left = start; left < middle; left ++) {
while (right < end && (long)nums [left] > (long) 2 * nums [right]) {
right ++;
}
count += right - middle;
}
mergeSort (nums, copiedNums, start, end);
return count;
}
private void mergeSort (int[] nums, int[] copiedNums, int start, int end) {
if (start + 1 == end) {
return;
}
int middle = start + (end - start) / 2;
int i = start;
int j = middle;
int copyStart = start;
while (i < middle && j < end) {
if (nums[i] < nums[j]) {
copiedNums [copyStart ++] = nums[i++];
} else {
copiedNums [copyStart ++] = nums[j++];
}
}
while (i < middle) {
copiedNums [copyStart ++] = nums[i++];
}
while (j < end) {
copiedNums [copyStart ++] = nums[j++];
}
//System.out.println (Arrays.toString(copiedNums));
for (i = start; i < end; i++) {
nums [i] = copiedNums[i];
}
//System.out.println (Arrays.toString(nums));
}
}