- Count of Smaller Numbers After Self
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:
Input: [5,2,6,1]
Output: [2,1,1,0]
Explanation:
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.
用归并排序解决:(也可以用BST,还没试,以后再说)
int[] counts; //设置全局变量,在merge的时候改变其值
public List<Integer> countSmaller(int[] nums) {
List<Integer> res = new ArrayList<Integer>();
int[] index = new int[nums.length]; //根据元素大小排序其索引,而非直接排序元素,因为counts[]在merge的时候要根据数组原索引增加值。
for(int i = 0; i < nums.length; i++){
index[i] = i;
}
counts = new int[nums.length];
mergeSort(nums,index,0,nums.length-1);
for(int i = 0; i < counts.length; i++){
res.add(counts[i]);
}
return res;
}
public void mergeSort(int[] nums, int[] index, int start, int end){
if(start >= end) return;
int mid = start + (end - start) / 2;
mergeSort(nums,index,start,mid);
mergeSort(nums,index,mid+1,end);
merge(nums,index,start,mid,end);
}
public void merge(int[] nums, int[] index, int start, int mid, int end){
int[] newIndex = new int[end - start + 1]; //这里要注意,我一开设置成new int[nums.length]
//然后在最下面for循环重新赋值
//就是for(int i = start; i <= end; i++){
// index[i] = newIndex[i];
// } 这样时间复杂度加了很多,不好。
int rightCount = 0;
int leftIdx = start;
int rightIdx = mid + 1;
int sort_index = 0;
while(leftIdx <= mid && rightIdx <= end){
if(nums[index[leftIdx]] <= nums[index[rightIdx]]){
counts[index[leftIdx]] += rightCount;
newIndex[sort_index++] = index[leftIdx++];
}else{
rightCount++;
newIndex[sort_index++] = index[rightIdx++];
}
}
while(leftIdx <= mid){
counts[index[leftIdx]] += rightCount;
newIndex[sort_index++] = index[leftIdx++];
}
while(rightIdx <= end){
newIndex[sort_index++] = index[rightIdx++];
}
for(int i = start; i <= end; i++){
index[i] = newIndex[i-start];
}
}