LeetCode 1365: How Many Numbers Are Smaller Than the Current Number (Frequency Prefix Counting)
LeetCode 1365ArrayCountingToday we solve LeetCode 1365 - How Many Numbers Are Smaller Than the Current Number.
Source: https://leetcode.com/problems/how-many-numbers-are-smaller-than-the-current-number/
English
Problem Summary
For each element nums[i], return how many elements in the array are strictly smaller than it.
Key Insight
Constraints are small: 0 <= nums[i] <= 100. Build a frequency array of size 101, then compute prefix counts so each value v can instantly map to how many numbers are smaller than v.
Brute Force and Limitations
Brute force compares every pair and costs O(n²). Sorting with original indices works in O(n log n), but counting-array prefix is simpler and faster here.
Optimal Algorithm Steps
1) Build freq[0..100].
2) Build prefix less[v] = count of numbers < v.
3) For each nums[i] = x, answer is less[x].
4) Return result array.
Complexity Analysis
Time: O(n + K), where K=101.
Space: O(K) (excluding output array).
Common Pitfalls
- Using prefix[v] directly as "smaller" (that includes v itself).
- Forgetting value range and allocating too small count array.
- Accidentally counting <= instead of strictly <.
Reference Implementations (Java / Go / C++ / Python / JavaScript)
class Solution {
public int[] smallerNumbersThanCurrent(int[] nums) {
int[] freq = new int[101];
for (int x : nums) freq[x]++;
int[] less = new int[101];
int running = 0;
for (int v = 0; v <= 100; v++) {
less[v] = running;
running += freq[v];
}
int[] ans = new int[nums.length];
for (int i = 0; i < nums.length; i++) {
ans[i] = less[nums[i]];
}
return ans;
}
}func smallerNumbersThanCurrent(nums []int) []int {
freq := make([]int, 101)
for _, x := range nums {
freq[x]++
}
less := make([]int, 101)
running := 0
for v := 0; v <= 100; v++ {
less[v] = running
running += freq[v]
}
ans := make([]int, len(nums))
for i, x := range nums {
ans[i] = less[x]
}
return ans
}class Solution {
public:
vector<int> smallerNumbersThanCurrent(vector<int>& nums) {
vector<int> freq(101, 0), less(101, 0);
for (int x : nums) freq[x]++;
int running = 0;
for (int v = 0; v <= 100; ++v) {
less[v] = running;
running += freq[v];
}
vector<int> ans;
ans.reserve(nums.size());
for (int x : nums) ans.push_back(less[x]);
return ans;
}
};from typing import List
class Solution:
def smallerNumbersThanCurrent(self, nums: List[int]) -> List[int]:
freq = [0] * 101
for x in nums:
freq[x] += 1
less = [0] * 101
running = 0
for v in range(101):
less[v] = running
running += freq[v]
return [less[x] for x in nums]var smallerNumbersThanCurrent = function(nums) {
const freq = new Array(101).fill(0);
for (const x of nums) freq[x]++;
const less = new Array(101).fill(0);
let running = 0;
for (let v = 0; v <= 100; v++) {
less[v] = running;
running += freq[v];
}
return nums.map(x => less[x]);
};中文
题目概述
对数组中每个元素 nums[i],计算数组里有多少元素严格小于它。
核心思路
本题数值范围很小(0..100),可直接用计数数组。先统计每个值出现次数,再做前缀累计,就能在 O(1) 时间得到任意值对应的“小于它的数量”。
暴力解法与不足
暴力双循环是 O(n²);排序 + 索引回填是 O(n log n)。在这个范围下,计数前缀法更直接、常数更小。
最优算法步骤
1)统计 freq[0..100]。
2)构建 less[v],表示严格小于 v 的元素个数。
3)遍历原数组,ans[i] = less[nums[i]]。
4)返回答案。
复杂度分析
时间复杂度:O(n + K),其中 K=101。
空间复杂度:O(K)(不计输出数组)。
常见陷阱
- 把包含自身频次的前缀和当成答案,导致变成 <=。
- 忘记题目取值范围,数组开小导致越界。
- 比较条件写成小于等于,语义错误。
多语言参考实现(Java / Go / C++ / Python / JavaScript)
class Solution {
public int[] smallerNumbersThanCurrent(int[] nums) {
int[] freq = new int[101];
for (int x : nums) freq[x]++;
int[] less = new int[101];
int running = 0;
for (int v = 0; v <= 100; v++) {
less[v] = running;
running += freq[v];
}
int[] ans = new int[nums.length];
for (int i = 0; i < nums.length; i++) {
ans[i] = less[nums[i]];
}
return ans;
}
}func smallerNumbersThanCurrent(nums []int) []int {
freq := make([]int, 101)
for _, x := range nums {
freq[x]++
}
less := make([]int, 101)
running := 0
for v := 0; v <= 100; v++ {
less[v] = running
running += freq[v]
}
ans := make([]int, len(nums))
for i, x := range nums {
ans[i] = less[x]
}
return ans
}class Solution {
public:
vector<int> smallerNumbersThanCurrent(vector<int>& nums) {
vector<int> freq(101, 0), less(101, 0);
for (int x : nums) freq[x]++;
int running = 0;
for (int v = 0; v <= 100; ++v) {
less[v] = running;
running += freq[v];
}
vector<int> ans;
ans.reserve(nums.size());
for (int x : nums) ans.push_back(less[x]);
return ans;
}
};from typing import List
class Solution:
def smallerNumbersThanCurrent(self, nums: List[int]) -> List[int]:
freq = [0] * 101
for x in nums:
freq[x] += 1
less = [0] * 101
running = 0
for v in range(101):
less[v] = running
running += freq[v]
return [less[x] for x in nums]var smallerNumbersThanCurrent = function(nums) {
const freq = new Array(101).fill(0);
for (const x of nums) freq[x]++;
const less = new Array(101).fill(0);
let running = 0;
for (let v = 0; v <= 100; v++) {
less[v] = running;
running += freq[v];
}
return nums.map(x => less[x]);
};
Comments