Find number of pairs where i < j and nums[i] > 2 * nums[j] using modified merge sort.
Problem Statement
Given an integer array `nums`, return the number of reverse pairs in the array.
A reverse pair is a pair `(i, j)` where `0 <= i < j < nums.length` and `nums[i] > 2 * nums[j]`.
Examples
Input: nums = [1, 3, 2, 3, 1]
Output: 2
Explanation: The reverse pairs are: (1, 4) -> 3 > 2 * 1, and (3, 4) -> 3 > 2 * 1.
Input: nums = [2, 4, 3, 5, 1]
Output: 3
Explanation: Combining the input according to Reverse Pairs logic yields 3.
Complexity
Time Complexity: O(N log N)
Space Complexity: O(N)
Hints
š” Hint 1:
A reverse pair is (i, j) such that i < j and nums[i] > 2 * nums[j].
š” Hint 2:
Like inversion counting, this can be solved during Merge Sort in O(N log N).
š” Hint 3:
Before merging two sorted halves, use two pointers to count all pairs where nums[i] > 2 * nums[j].
Editorial & Approach
Problem Overview & Intuition
A reverse pair requires nums[i] > 2 * nums[j] with i < j. Using Divide and Conquer (Merge Sort), because both left and right subarrays are sorted, for each left element we can advance a pointer in the right subarray monotonically in O(N) time per level.
Step-by-Step Approach
- Divide
numsrecursively using merge sort. - Count reverse pairs between the sorted halves before merging: loop
iin left, advancerightPtrwhilenums[i] > 2 * nums[rightPtr]. - Merge the two sorted halves.
- Return total reverse pairs.
Optimal Implementation (JavaScript)
function reversePairs(nums) {
function mergeSort(left, right) {
if (left >= right) return 0;
const mid = Math.floor((left + right) / 2);
let count = mergeSort(left, mid) + mergeSort(mid + 1, right);
count += countPairs(left, mid, right);
merge(left, mid, right);
return count;
}
function countPairs(left, mid, right) {
let count = 0, rightPtr = mid + 1;
for (let i = left; i <= mid; i++) {
while (rightPtr <= right && nums[i] > 2 * nums[rightPtr]) rightPtr++;
count += (rightPtr - (mid + 1));
}
return count;
}
function merge(left, mid, right) {
const temp = [];
let i = left, j = mid + 1;
while (i <= mid && j <= right) {
if (nums[i] <= nums[j]) temp.push(nums[i++]);
else temp.push(nums[j++]);
}
while (i <= mid) temp.push(nums[i++]);
while (j <= right) temp.push(nums[j++]);
for (let p = 0; p < temp.length; p++) nums[left + p] = temp[p];
}
return mergeSort(0, nums.length - 1);
}
Complexity Analysis
Time Complexity
O(N log N) ā O(N) work per recursion level.
Space Complexity
O(N) ā auxiliary storage for merging.
Edge Cases & Corner Traps Handled
- Single element array: returns 0.
- Negative numbers: properly compared.
- Array sorted in ascending order.