You are given an integer array nums and you have to return a new counts array. The counts array has the property where counts[i]
is the number of smaller elements to the right of nums[i]
.
Example:
Given nums = [5, 2, 6, 1] To the right of 5 there are 2 smaller elements (2 and 1). To the right of 2 there is only 1 smaller element (1). To the right of 6 there is 1 smaller element (1). To the right of 1 there is 0 smaller element.
Return the array [2, 1, 1, 0]
.
思路:MergeSort,但是要记录数据在变化过程中的index变化,即最开始在哪要维持
import java.util.ArrayList;
import java.util.List;
public class Solution {
// indexMap: 现在的index对应原来的indexMap[index]
int[] indexMap, dumpIndexMap, smaller;
public List<Integer> countSmaller(int[] nums) {
indexMap = new int[nums.length];
for(int i=0; i<nums.length; i++) indexMap[i] = i;
dumpIndexMap = new int[nums.length];
smaller = new int[nums.length];
sort(nums, new int[nums.length], 0, nums.length-1);
List<Integer> rst = new ArrayList<Integer>();
for(int i : smaller) rst.add(i);
return rst;
}
public void sort(int[] a, int[] aux, int lo, int hi) {
if(hi <= lo) return;
int mid = lo + (hi - lo) / 2;
sort(a, aux, lo, mid);
sort(a, aux, mid+1, hi);
merge(a, aux, lo, mid, hi);
}
private void merge(int[] a, int[] aux, int lo, int mid, int hi) {
// 原始数组需要保存一份,indexMap也需要保存一份
// 否则赋值给indexMap[k]就可能不正确
for(int k=lo; k<=hi; k++) {
aux[k] = a[k];
dumpIndexMap[k] = indexMap[k];
}
int i = lo, j = mid+1;
for(int k=lo; k<=hi; k++) {
if(i > mid) {
a[k] = aux[j++];
indexMap[k] = dumpIndexMap[j-1];
} else if(j > hi) {
a[k] = aux[i++];
indexMap[k] = dumpIndexMap[i-1];
smaller[indexMap[k]] += j-mid-1;
} else if(aux[j] < aux[i]) {
a[k] = aux[j++];
indexMap[k] = dumpIndexMap[j-1];
} else {
a[k] = aux[i++];
indexMap[k] = dumpIndexMap[i-1];
smaller[indexMap[k]] += j-mid-1;
}
}
}
}
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.
思路:上一题的变行,注意数据溢出的问题
public class Solution {
int ret = 0;
public int reversePairs(int[] nums) {
if(nums.length == 0) return 0;
sort(nums, new int[nums.length], 0, nums.length-1);
return ret;
}
public void sort(int[] a, int[] aux, int s, int t) {
if(s == t) return;
int mid = (s + t) / 2;
sort(a, aux, s, mid);
sort(a, aux, mid+1, t);
merge(a, aux, s, mid, t);
}
private void merge(int[] a, int[] aux, int s, int mid, int t) {
for(int i=s; i<=t; i++) aux[i] = a[i];
// BS find the last position smaller than a[s..mid]/2
for(int i=s; i<=mid; i++) {
int p = bs(a, mid+1, t, a[i]>0 && a[i]%2==1 ? a[i]/2 : a[i]/2-1);
ret += p - mid;
}
int p = s, q = mid+1;
for(int i=s; i<=t; i++) {
if(p > mid) a[i] = aux[q++];
else if(q > t) a[i] = aux[p++];
else if(aux[q]<aux[p]) a[i] = aux[q++];
else a[i] = aux[p++];
}
}
public int bs(int[] a, int lo, int hi, int t) {
if(a[lo] > t) return lo-1;
while(lo+1 < hi) {
int mid = (lo + hi) / 2;
if(a[mid] > t) hi = mid - 1;
else lo = mid;
}
return a[hi] <= t ? hi : lo;
}
}