#1365. 有多少小于当前数字的数字
难度:简单
题目描述
解题思路
1、桶排序 O(n)
因为题目里限制了数组中元素的范围0~100,所以采用桶排序是一种效率很高的方式
public int[] smallerNumbersThanCurrent(int[] nums) {
int count[] = new int [101];
for(int num:nums) {
count[num]++;
}
int re[] = new int [nums.length];
for (int i = 0; i < re.length; i++) {
int j = 0;
while(j++ < nums[i]) {
re[i] += count[j];
}
}
return re;
}
这种是比较笨的,最后循环累加得到结果。
可以直接对桶进行累加,这样每个桶内保存的都是比下个数小的个数,书简复杂度O(n)
public int[] smallerNumbersThanCurrent(int[] nums) {
int count[] = new int [101];
for(int num:nums) {
count[num]++;
}
for (int i = 1; i < count.length; i++) { //一次遍历累加,记录比这个数小的个数
count[i] += count[i-1];
}
int re[] = new int [nums.length];
for (int i = 0; i < re.length; i++) {
re[i] = nums[i] != 0?count[nums[i]-1]:0;
}
return re;
}
2、排序加映射
其实思路都差不多,就是实现方式不一样。用哈希表来保存每个值和对应的下标,然后对数组进行排序。排序之后的数组里每个数下标就是比这个数小的个数
public int[] smallerNumbersThanCurrent1(int[] nums) {
int len = nums.length;
Map<Integer, Set<Integer>> valueIndex = new HashMap<>(len); // 预存每个值与索引对应
for (int i = 0; i < len; i++) {
if (!valueIndex.containsKey(nums[i]))
valueIndex.put(nums[i], new HashSet<>());
valueIndex.get(nums[i]).add(i);
}
int[] sortedArr = Arrays.copyOf(nums, len), res = new int[len];
Arrays.sort(sortedArr); // 1, 2, 2, 3, 8
for (int si = len - 1; si >= 0; si--) { // 倒序,方便处理同值的情况
for (int i : valueIndex.get(sortedArr[si])) res[i] = si; // 同值的所有索引都更新
}
return res;
}