给定一个整数数组 nums,按要求返回一个新数组 counts。数组 counts 有该性质: counts[i]
的值是 nums[i]
右侧小于 nums[i]
的元素的数量。
示例:
输入: [5,2,6,1]
输出: [2,1,1,0] **解释:**
5 的右侧有 2 个更小的元素 (2 和 1).
2 的右侧仅有 1 个更小的元素 (1).
6 的右侧有 1 个更小的元素 (1).
1 的右侧有 0 个更小的元素.
思路
使用归并排序
class Solution {
class Node{
int i;
int value;
}
// 计算右侧小于当前元素的个数
public List<Integer> countSmaller(int[] nums) {
List<Integer> list = new ArrayList<Integer>();
Node[] nodes = new Node[nums.length];
for(int i=0;i<nums.length;i++){
Node nn= new Node();
nodes[i] = nn;
nodes[i].value = nums[i];
nodes[i].i = i;
}
int[] result = new int[nums.length];
mergeSort(nodes,0,nums.length-1,result);
for(int i=0;i<result.length;i++){
list.add(result[i]);
}
return list;
}
private void mergeSort(Node[] nodes,int left,int right, int[] result){
if(left<right){
int mid = left+(right-left)/2;
mergeSort(nodes,left,mid,result);
mergeSort(nodes,mid+1,right,result);
//整合
int i=left;
int j = mid+1;
Node[] nodesC = new Node[right-left+1];
int index = 0;
while(i<=mid && j<=right){
if(nodes[i].value > nodes[j].value){
nodesC[index++]=nodes[j++];
}else{
// 如果此时放入了nodes[i],说明右半部分有j-1-mid个数比它小
result[nodes[i].i]+=j-1-mid;
nodesC[index++]=nodes[i++];
}
}
while(i<=mid){
//同理
result[nodes[i].i]+=right-mid;
nodesC[index++]=nodes[i++];
}
while(j<=right){
nodesC[index++] = nodes[j++];
}
for(i=0;i<nodesC.length;i++){
nodes[left++]=nodesC[i];
}
}
}
}