class Solution:
def reversePairs(self, nums):
def merge_sort(arr, left, right):
if left >= right:
return 0
mid = (left + right) // 2
count = merge_sort(arr, left, mid) + merge_sort(arr, mid + 1, right)
# Count reverse pairs
j = mid + 1
for i in range(left, mid + 1):
while j <= right and arr[i] > 2 * arr[j]:
j += 1
count += j - (mid + 1)
# Merge step
temp = []
l, r = left, mid + 1
while l <= mid and r <= right:
if arr[l] <= arr[r]:
temp.append(arr[l])
l += 1
else:
temp.append(arr[r])
r += 1
while l <= mid:
temp.append(arr[l])
l += 1
while r <= right:
temp.append(arr[r])
r += 1
arr[left:right+1] = temp
return count
return merge_sort(nums, 0, len(nums) - 1)
class Solution {
public:
int mergeSort(vector<int>& nums, int left, int right) {
if (left >= right) return 0;
int mid = left + (right - left) / 2;
int count = mergeSort(nums, left, mid) + mergeSort(nums, mid + 1, right);
int j = mid + 1;
for (int i = left; i <= mid; ++i) {
while (j <= right && (long long)nums[i] > 2LL * nums[j]) j++;
count += j - (mid + 1);
}
// Merge
vector<int> temp;
int l = left, r = mid + 1;
while (l <= mid && r <= right) {
if (nums[l] <= nums[r]) temp.push_back(nums[l++]);
else temp.push_back(nums[r++]);
}
while (l <= mid) temp.push_back(nums[l++]);
while (r <= right) temp.push_back(nums[r++]);
for (int i = left; i <= right; ++i) nums[i] = temp[i - left];
return count;
}
int reversePairs(vector<int>& nums) {
return mergeSort(nums, 0, nums.size() - 1);
}
};
class Solution {
public int reversePairs(int[] nums) {
return mergeSort(nums, 0, nums.length - 1);
}
private int mergeSort(int[] nums, int left, int right) {
if (left >= right) return 0;
int mid = left + (right - left) / 2;
int count = mergeSort(nums, left, mid) + mergeSort(nums, mid + 1, right);
int j = mid + 1;
for (int i = left; i <= mid; i++) {
while (j <= right && (long)nums[i] > 2 * (long)nums[j]) j++;
count += j - (mid + 1);
}
// Merge
int[] temp = new int[right - left + 1];
int l = left, r = mid + 1, k = 0;
while (l <= mid && r <= right) {
if (nums[l] <= nums[r]) temp[k++] = nums[l++];
else temp[k++] = nums[r++];
}
while (l <= mid) temp[k++] = nums[l++];
while (r <= right) temp[k++] = nums[r++];
for (int i = 0; i < temp.length; i++) nums[left + i] = temp[i];
return count;
}
}
var reversePairs = function(nums) {
function mergeSort(arr, left, right) {
if (left >= right) return 0;
let mid = Math.floor((left + right) / 2);
let count = mergeSort(arr, left, mid) + mergeSort(arr, mid + 1, right);
let j = mid + 1;
for (let i = left; i <= mid; i++) {
while (j <= right && arr[i] > 2 * arr[j]) j++;
count += j - (mid + 1);
}
// Merge
let temp = [];
let l = left, r = mid + 1;
while (l <= mid && r <= right) {
if (arr[l] <= arr[r]) temp.push(arr[l++]);
else temp.push(arr[r++]);
}
while (l <= mid) temp.push(arr[l++]);
while (r <= right) temp.push(arr[r++]);
for (let i = left; i <= right; i++) arr[i] = temp[i - left];
return count;
}
return mergeSort(nums, 0, nums.length - 1);
};
Given an array of integers nums
, count the number of reverse pairs in the array. A reverse pair is defined as a pair of indices (i, j)
where i < j
and nums[i] > 2 * nums[j]
.
nums
can be used only in its original position; you cannot reuse elements for different indices.i
and j
must satisfy i < j
.Constraints:
1 <= nums.length <= 5 * 10^4
-2^{31} <= nums[i] <= 2^{31} - 1
The most direct approach is to check every possible pair (i, j)
and count if nums[i] > 2 * nums[j]
. This brute-force method is simple to implement but inefficient for large arrays because it checks every possible pair, leading to a time complexity of O(n2).
However, since the array can be quite large (up to 50,000 elements), a more efficient approach is needed. We notice that the problem is similar to counting inversions in an array, which can be efficiently solved using a modified merge sort. The key insight is that during the merge step, both halves are sorted, allowing us to count reverse pairs efficiently by using two pointers.
The optimized approach leverages the divide-and-conquer paradigm, splitting the array, counting reverse pairs in each half, and then counting pairs that span the two halves, all while sorting the array.
nums[i] > 2 * nums[j]
.j
for each i
.This approach ensures that each pair is counted exactly once, and the overall time complexity is reduced to O(n log n).
Consider the input nums = [1, 3, 2, 3, 1]
.
The merge sort approach counts these efficiently without redundant checks.
(i, j)
.The optimized approach is essential for handling large arrays efficiently.
To solve the Reverse Pairs problem efficiently, we use a modified merge sort algorithm. This approach leverages the sorted nature of subarrays during merging to count reverse pairs in O(n log n) time, a significant improvement over the brute-force O(n2) method. The key insight is to recognize the similarity to the inversion count problem and adapt the merge step to count pairs meeting the specific condition nums[i] > 2 * nums[j]
. This solution is both elegant and efficient, making it suitable for large input sizes.