315. 计算右侧小于当前元素的个数
Posted 不吐西瓜籽
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了315. 计算右侧小于当前元素的个数相关的知识,希望对你有一定的参考价值。
算法记录
LeetCode 题目:
给你一个整数数组 nums ,按要求返回一个新数组 counts 。数组 counts 有该性质: counts[i] 的值是 nums[i] 右侧小于 nums[i] 的元素的数量。
说明
一、题目
给你一个整数数组 nums ,按要求返回一个新数组 counts 。数组 counts 有该性质: counts[i] 的值是 nums[i] 右侧小于 nums[i] 的元素的数量。
二、分析
- 可以直接用暴力的方法,遍历两次数组来计算。
- 题目需要的是当
j
>i
时,有nums[i]
>nums[j]
,就可以构建一个逆向排序数组,只要当前的j
小于当前i
,那么剩下的区间数也必定是小于i
的,直接累加即可。 - 需要注意的是题目中的元素值是可以重复的,定义下标时就不能简单的构建一个下标映射字典或者下标数组的来解决,定义一个内部类来解决。
class Solution {
class Index{
public Integer val;
public Integer index;
public Index(int val, int index) {
this.val = val;
this.index = index;
}
}
private Index[] index;
public List<Integer> countSmaller(int[] nums) {
Integer[] ans = new Integer[nums.length];
index = new Index[nums.length];
for(int i = 0; i < nums.length; i++) {
index[i] = new Index(nums[i], i);
ans[i] = 0;
}
sort(index, 0, nums.length - 1, ans);
return Arrays.asList(ans);
}
public void sort(Index[] nums, int start, int end, Integer[] ans) {
if(start >= end) return ;
int middle = (start + end) >> 1;
sort(nums, start, middle, ans);
sort(nums, middle + 1, end, ans);
merge(nums, start, middle, middle + 1, end, ans);
}
public void merge(Index[] nums, int l1, int r1, int l2, int r2, Integer[] ans) {
List<Index> temp = new ArrayList();
int i = l1, j = l2;
while(i <= r1 || j <= r2) {
if(j > r2 || (i <= r1 && nums[i].val > nums[j].val)) {
temp.add(nums[i]);
ans[nums[i].index] += r2 - j + 1;
i++;
} else {
temp.add(nums[j]);
j++;
}
}
for(i = l1; i <= r2; i++) nums[i] = temp.get(i - l1);
}
}
总结
熟悉归并退层的结构特点。
以上是关于315. 计算右侧小于当前元素的个数的主要内容,如果未能解决你的问题,请参考以下文章