1、题目
计算右侧小于当前元素的个数 - 力扣(LeetCode) https://leetcode-cn.com/problems/count-of-smaller-numbers-after-self/submissions/
2、题解
这道题的题面很简单。就是计算在元素右侧比该元素小的个数。
首先想到的自然是暴力法,两次循环遍历,直接比较,时间复杂度是O(n^2).超出时间限制。
之后看了一下题解的思路,研究了一下归并排序,在归的部分就是把整个数组不断二分,在并的部分就是将二分的部分合一,并且通过在并的同时计算逆序数,从而得到该点的结果。使用归并算法,时间复杂度是O(nlgn).
3、代码
//归并排序的利用
class Solution {
private int[] indexs;//索引数组
private int[] temp;//归并临时
private int[] resultArray;//结果数组
public List<Integer> countSmaller(int[] nums) {
ArrayList<Integer> result = new ArrayList<>();
int length = nums.length;
if(length==0){
return result;
}
indexs=new int[length];
temp=new int[length];
resultArray=new int[length];
for (int i = 0; i < length; i++) {
indexs[i]=i;
}
mergeSort(nums,0,length-1);
for (int j = 0; j <length ; j++) {
result.add(resultArray[j]);
}
return result;
}
private void mergeSort(int[] nums, int Left, int Right) {
if(Left==Right){
return;
}
int mid = Left+(Right-Left)/2;
mergeSort(nums,Left,mid);
mergeSort(nums,mid+1,Right);
if(nums[indexs[mid]]>nums[indexs[mid+1]]){
merge(nums,Left,mid,Right);
}
}
private void merge(int[] nums, int left, int mid, int right) {
for (int i = left; i <=right ; i++) {
temp[i]=indexs[i];
}
int p1=left;
int p2=mid+1;
//归并大法
for (int k = left; k <=right; k++) {
if(p1>mid){
//1、p1耗光了
indexs[k]=temp[p2];
p2++;
}else if(p2>right){
//2、p2耗光了
indexs[k]=temp[p1];
p1++;
resultArray[indexs[k]]+=(right-mid);
}else if(nums[temp[p1]]<=nums[temp[p2]]){
//3、前序小于后序
indexs[k]=temp[p1];
p1++;
resultArray[indexs[k]]+=(p2-mid-1);
}else {
//4、后序小于前序
indexs[k]=temp[p2];
p2++;
}
}
}
}
网友评论