赞
踩
给定一个整数数组 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 个更小的元素.
思路:我们先看另一道题:
给你一个数组,对于每个位置i,求出所有在i之前的比位置i上的数大的数
这不就是求逆序数嘛,这道题不是大同小异嘛,我们想一下求逆序数比较快速的方法,树状数组? 归并排序?线段树?
其实都是可以的,我们采用比较常用的归并排序吧。
对于三个数组的解释:
temp:存储元素的初始索引
indexes:存储元素排序后的最终索引
counter:每个位置上的答案
- class Solution {
- private int[] temp;
- private int[] counter;
- private int[] indexes;
- public List<Integer> countSmaller(int[] nums) {
- List<Integer> res=new ArrayList<>();
- int len=nums.length;
- if(len==0) return res;
-
- temp=new int[len];
- counter=new int[len];
- indexes=new int[len];
-
- for(int i=0;i<len;i++) indexes[i]=i;
-
- mergeAndCountSmaller(nums,0,len-1);
-
- for(int i=0;i<len;i++)
- res.add(counter[i]);
-
- return res;
- }
-
- private void mergeAndCountSmaller(int[] nums,int l,int r)
- {
- if(l==r) return;
-
- int mid=l+(r-l)/2;
- mergeAndCountSmaller(nums,l,mid);
- mergeAndCountSmaller(nums,mid+1,r);
-
- if(nums[indexes[mid]]>nums[indexes[mid+1]])
- mergeOfTwoSortedArrAndCountSmaller(nums,l,mid,r);
- }
-
- private void mergeOfTwoSortedArrAndCountSmaller(int[] nums,int l,int mid,int r)
- {
- for(int i=l;i<=r;i++)
- temp[i]=indexes[i];
- int i=l,j=mid+1;
- for(int k=l;k<=r;k++)
- {
- if(i>mid)
- {
- indexes[k]=temp[j];
- j++;
- }
- else if(j>r)
- {
- indexes[k]=temp[i];
- i++;
- counter[indexes[k]]+=r-mid;
- }
- else if(nums[temp[i]]<=nums[temp[j]])
- {
- indexes[k]=temp[i];
- i++;
- counter[indexes[k]]+=(j-mid-1);
- }
- else
- {
- indexes[k]=temp[j];
- j++;
- }
- }
- }
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。