问题:1365. 有多少小于当前数字的数字
给你一个数组 nums,对于其中每个元素 nums[i],请你统计数组中比它小的所有数字的数目。
换而言之,对于每个 nums[i] 你必须计算出有效的 j 的数量,其中 j 满足 j != i 且 nums[j] < nums[i] 。
以数组形式返回答案。
分析
分析:首先这个题规定数字不会超过100,那么我们开辟一个数组,长度为101,整个理解为一个桶,数组的i
位置对应了数字i
在nums中出现的个数。所以,数组初始值都为零。遍历一遍nums来记录每个位置的出现的个数。
下面这句话是整个代码的核心:如果拿到一个有序的序列,那么对于其中的一个数字num,在这个序列中小于他的数字的个数等于位于他前面的数字出现的个数。
在我们的桶中,数字是有序的,因为我们开辟了101个位置,一定包括了nums里面的全部数字,那么对于数组[8,1,2,2,3]
来说,其在桶中的是这样体现的:[0,1,2,1,0,0,0,0,1.0.......]
。这是每个数字出现的个数,那么如何得到题目要求的呢?
按照前面说的规律:
- 数字1小于他数字的个数等于位于其前面的数字的个数,1之前是0,而不存在比0 小的数,所以1对应的答案是0;
- 对于数字2来说,1比他小,1出现的个数是1,出现的个数是0,则2对应的答案是1;
- 数字3:1出现1次,2出现2次,0没出现,所以结果是3.
- 数字4虽然没出现在数组中,但是作为桶的内容,它也要计算,是为了保证后面出现的数的计算正确性。
- 数字8:其前面出现的个数和为4,结果为4;
到这里我们发现规律了,对于0来说,0的位置是0。i位置的答案等于其前面所有元素出现的和。我们是不是每次都要计算全部的和呢?当然不需要。
这里我觉得是DP的思想,在桶中,小于num的数字出现的个数等于:小于num-1的数字出现的个数+num-1这个数字出现的个数。 所以,我们需要累加每个位置的值,这样在桶中i-1
位置对应的值就是小于i
的数字出现的个数了。
Code
class Solution {
public int[] smallerNumbersThanCurrent(int[] nums) {
int[] count = new int[101];
// 计数
for (int i = 0; i < nums.length; i++) count[nums[i]]++;
// 计算数字出现的个数
for (int i = 1; i < count.length; i++) count[i] += count[i-1];
// 返回结果
for (int i = 0; i < nums.length; i++) nums[i] = nums[i] == 0 ? 0 : count[nums[i]-1];
return nums;
}
}