You are given an integer arraynumsand you have to return a newcountsarray. Thecountsarray has the property wherecounts[i]
is the number of smaller elements to the right ofnums[i]
.
Copy 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.
Copy class Solution {
public List < Integer > countSmaller ( int [] nums) {
List < Integer > res = new ArrayList <>();
if (nums == null || nums . length == 0 ) {
return res;
}
int n = nums . length ;
// count[i]表示,在nums排序前,i位置上的数的count of smaller numbers
int [] count = new int [n];
// index存的是nums中每个数对应的位置,index[i]表示,在nums排序前,第i位置上的数在归并过程中的位置
int [] index = new int [n];
for ( int i = 0 ; i < n; i ++ ) {
index[i] = i;
}
mergeSort(nums , index , count , 0 , n - 1 ) ;
for ( int i : count) {
res . add (i);
}
return res;
}
public void mergeSort ( int [] nums , int [] index , int [] count , int start , int end) {
if (start >= end) {
return ;
}
int mid = start + (end - start) / 2 ;
mergeSort(nums , index , count , start , mid) ;
mergeSort(nums , index , count , mid + 1 , end) ;
merge(nums , index , count , start , mid , end) ;
}
public void merge ( int [] nums , int [] index , int [] count , int start , int mid , int end) {
int [] temp = new int [end - start + 1 ];
int i = start;
int j = mid + 1 ;
int k = 0 ;
int rightCount = 0 ;
while (i <= mid && j <= end) {
// index[j]在归并排序的后半部分,如果nums[index[j]] < nums[index[i]] 说明index[j]所对应的数在nums中原本是在index[i]对应的数后面,而nums[index[j]] < nums[index[i]], 说明我们找到一个符合条件的count of smaller number, 所以rightCount加一
if (nums[index[j]] < nums[index[i]]) {
// 注意这里temp存储的是数字对应的位置,不是数字的值,这和传统的merge sort不同
temp[k] = index[j];
++ rightCount;
++ j;
}
// 当nums[index[j]] >= nums[index[i]]时,因为index[i]对应的数在[index[j]对应的数前面,而index[i]的count of smaller number就是rightCount
else {
temp[k] = index[i];
count[index[i]] += rightCount;
++ i;
}
++ k;
}
while (i <= mid) {
temp[k] = index[i];
count[index[i]] += rightCount;
++ k;
++ i;
}
while (j <= end) {
temp[k] = index[j];
++ k;
++ j;
}
// 将合并完成后的数组所对应的位置重新存放在index中
for ( int m = start; m <= end; m ++ ) {
index[m] = temp[m - start];
}
}
}
3. Time & Space Complexity