Given an array nums
, we call(i, j)
an important reverse pair if i < j
andnums[i] > 2*nums[j]
.java
You need to return the number of important reverse pairs in the given array.數組
Example1:優化
Input: [1,3,2,3,1]
Output: 2code
Example2:排序
Input: [2,4,3,5,1]
Output: 3input
Note:it
50,000
.這題能夠結合歸併排序的思路,將問題拆分爲兩個子問題,在分別計算出兩個子數組含有的重要反序組以後,再對跨兩個子數組的重要反序組進行排序。假設兩個子數組此時均爲有序,則只須要用二分法的思路,找到知足條件的最遠下標便可。代碼以下:class
public int reversePairs(int[] nums) { if (nums == null) { return 0; } long[] numsInLong = Arrays.stream(nums).asLongStream().toArray(); return reversePairs(numsInLong, 0, nums.length-1); } public int reversePairs(long[] nums, int left, int right) { if (left >= right) { return 0; } int mid = (left + right) / 2; int leftReversePairs = reversePairs(nums, left, mid); int rightReversePairs = reversePairs(nums, mid+1, right); int count = 0; int cur = mid; while(cur >= left) { int index = findRightMostIndex(nums, nums[cur], mid+1, right); int tmpCount = index - mid - 1; if (tmpCount == 0) { break; } count += tmpCount; cur--; } mergeSort(nums, left, right); return count + leftReversePairs + rightReversePairs; } public void mergeSort(long[] nums, int left, int right) { long[] copy = Arrays.copyOfRange(nums, left, right+1); int mid = (left + right) / 2 - left; int leftIndex = 0; int rightIndex = mid + 1; int index = left; while (index <= right) { if (rightIndex > right - left) { nums[index++] = copy[leftIndex++]; } else if (leftIndex > mid) { nums[index++] = copy[rightIndex++]; } else if (copy[leftIndex] <= copy[rightIndex]) { nums[index++] = copy[leftIndex++]; } else { nums[index++] = copy[rightIndex++]; } } } public int findRightMostIndex(long[] nums, long num, int left, int right) { while (left <= right) { int mid = (left + right) / 2; if (num > nums[mid] * 2) { left = mid + 1; } else { right = mid - 1; } } return left; }
這裏的一個優化點在於只複製一次完整的數組,減小不斷初始化子數組備份的過程。import