题目描述

✅ 1365. 有多少小于当前数字的数字

image-20260928224508077

image-20260928224508110

题意分析

对每个 nums[i],统计整个数组中严格小于它的元素个数,并将结果放在答案的相同下标处。统计的是出现次数,不是不同数字的种类数;相等的元素不计入。

解法:计数数组 + 前缀和

核心思路

[!blue]

如果对每个位置重新扫描全数组,会重复比较相同的数值。题目中所有数都在 $[0,100]$ 内,可以先用 freq[v] 记录值 $v$ 在整个数组中出现多少次,同一个值的答案便只需计算一次。

定义 prefix[v] 为严格小于 $v$ 的元素总数。因为输入没有负数,prefix[0] = 0;从 $v-1$ 到 $v$,新增的较小元素只有值恰好为 $v-1$ 的那些,所以 prefix[v] = prefix[v - 1] + freq[v - 1]。按值从小到大递推,就能得到所有查询结果。

最后仍按原数组下标遍历,令 answer[i] = prefix[nums[i]]。每个更小元素都按其频次计入,相等元素全部被排除;自身也不可能严格小于自身,因此不需要再减一。查表不会改变输入顺序,相同值自然得到相同答案。

解题步骤

  • 建立101格频次数组。
  • 从一到一百求排除自身值的前缀数量。
  • 按原下标查表生成答案。

代码实现

class Solution {
    public int[] smallerNumbersThanCurrent(int[] nums) {

        int[] freq = new int[101];

        for (int num : nums) {
            freq[num]++;
        }

        int[] prefix = new int[101];

        for (int i = 1; i <= 100; i++) {

            // 只累计到前一个值,保证不包含与当前值相等的元素。
            prefix[i] = prefix[i - 1] + freq[i - 1];
        }

        int[] answer = new int[nums.length];

        for (int i = 0; i < nums.length; i++) {
            // 按原下标查值域统计,重复值自然有相同答案。
            answer[i] = prefix[nums[i]];
        }

        return answer;
    }
}
func smallerNumbersThanCurrent(nums []int) []int {

    freq := make([]int, 101)
    for _, num := range nums {
        freq[num]++
    }

    prefix := make([]int, 101)
    for i := 1; i <= 100; i++ {

        // 只累计到前一个值,保证不包含与当前值相等的元素。
        prefix[i] = prefix[i-1] + freq[i-1]
    }

    answer := make([]int, len(nums))
    for i, num := range nums {
        // 按原下标查值域统计,重复值自然有相同答案。
        answer[i] = prefix[num]
    }

    return answer
}

复杂度分析

  • 时间复杂度:$O(n+101)$,统计频次与生成答案各遍历一次数组,前缀统计遍历固定值域。
  • 空间复杂度:$O(101)$ 辅助空间,输出另占 $O(n)$。

关键点总结

[!green]

  • 严格小于已经自动排除自身,无需再减一。
  • 零的答案为零,一百也必须有可查询的表项。

易错点总结

[!yellow]

  • 递推加当前频次会改变边界语义。
  • 数组只开一百格,合法值一百会越界。
  • 直接排序输入后按新位置返回,会丢掉原下标对应关系。

相似题目

题目 难度 关联与区别
35. 搜索插入位置 简单 在排序副本中寻找每个值的下界,下界下标就是严格较小元素的数量。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2024/83500816
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!