題目連接:
https://leetcode.com/problems...oop
和Count of Smaller Numbers After Self還有count of range sum是一類題,解法都差很少。BST能夠作,可是這道題若是輸入是有序的,簡單的bst會超時,因此得用AVL來作。
而後就是binary index tree的作法,計算大於nums[j]2的時候就是拿所有的sum減去sum(nums[j] 2)this
public class Solution { public int reversePairs(int[] nums) { int res = 0; int n = nums.length; if(n == 0) return res; // reflection Map<Long, Integer> map = new HashMap(); long[] sorted = new long[2*n]; for(int i = 0; i < n; i++) { sorted[2*i] = nums[i]; sorted[2*i + 1] = (long) nums[i] * 2; } Arrays.sort(sorted); int idx = 1; for(long num : sorted) { if(!map.containsKey(num)) map.put(num, idx++); } BIT t = new BIT(idx); int sum = 0; for(int j = 0; j < n; j++) { // find how many number > 2 * nums[j] long num = (long) nums[j]; res += sum - t.sum(map.get(num*2)); t.add(map.get(num), 1); sum++; } return res; } class BIT { int n; int[] tree; BIT(int n) { this.n = n; tree = new int[n]; } protected int sum(int i) { int res = 0; while(i > 0) { res += tree[i]; i -= i & -i; } return res; } protected void add(int i, int val) { while(i < n) { tree[i] += val; i += i & -i; } } } }
merge sort的作法,一樣是每次要統計左邊有多少結果是 > 2 * nums[j]的,每次sort完以後先算有多少pairs再merge。算pairs的方法是:
好比給的例子,如今分紅了左右兩部分[1, 1, 2], [3, 3],拿兩個指針i和j。指針
if nums[i]/2.0 > nums[j]
,表示全部小與等於nums[j]的值都知足這個條件,一直增大到不知足條件的,最後j - (mid+1)
就是所有知足該條件且包含nums[i]的pair數目code
else, 表示nums[i]小了,須要i++leetcode
loop的invariant用包含nums[j]的也行:get
ifnums[i]/2.0 > nums[j]
表示全部大於等於nums[i]的都知足條件,res += mid - i + 1
,同時j++io
else表示i小了,因此i++class
每次從新開一個aux就超時了,因此把aux當全局變量,開一次變量
public class Solution { public int reversePairs(int[] nums) { int n = nums.length; if(n == 0) return 0; // merge sort res = 0; aux = new int[n]; sort(nums, 0, n - 1); return res; } int res; int[] aux; private void sort(int[] nums, int l, int r) { if(l >= r) return; int mid = l + (r - l) / 2; sort(nums, l, mid); sort(nums, mid + 1, r); int i = l, j = mid + 1; while(j <= r) { while(i <= mid && nums[i]/2.0 <= nums[j]) i++; // count number of pairs include nums[j] res += mid - i + 1; j++; } merge(nums, l, mid, r); } private void merge(int[] nums, int l, int mid, int r) { for(int k = l; k <= r; k++) aux[k] = nums[k]; int i = l, j = mid + 1; for(int k = l; k <= r; k++) { if(i > mid) nums[k] = aux[j++]; else if(j > r) nums[k] = aux[i++]; else if(aux[i] > aux[j]) nums[k] = aux[j++]; else nums[k] = aux[i++]; } } }