力扣👊 1365. 有多少小于当前数字的数字

119 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第 4 天,点击查看活动详情

题目链接

1365. 有多少小于当前数字的数字 - 力扣(LeetCode) (leetcode-cn.com)

题目描述

给你一个数组 nums,对于其中每个元素 nums[i],请你统计数组中比它小的所有数字的数目。

换而言之,对于每个 nums[i] 你必须计算出有效的 j 的数量,其中 j 满足 j != inums[j] < nums[i] 

以数组形式返回答案。

测试用例

示例 1:

输入:nums = [8,1,2,2,3]
输出:[4,0,1,1,3]

解释: 
对于 nums[0]=8 存在四个比它小的数字:(1,2,2 和 3)。 
对于 nums[1]=1 不存在比它小的数字。
对于 nums[2]=2 存在一个比它小的数字:(1)。 
对于 nums[3]=2 存在一个比它小的数字:(1)。 
对于 nums[4]=3 存在三个比它小的数字:(1,2 和 2)。

限制

  • 2 <= nums.length <= 500
  • 0 <= nums[i] <= 100

题目分析

题目需要我们统计数组中,每个元素比他还小的值存在有多少个

由题目的示例可知他的元素不是有序的。为了提高匹配的效率,我们需要定义一个 map 记录每个元素出现的次数;同时,我们需要一个 keys 变量来记录出现过哪些元素,并且需要将他们有序排列

使用数组变量 result 表示 nums 对应位置的元素,出现的次数

最后使用双层 for 循环,外层遍历 nums,内层遍历 keys,记录下外层 for 当前遍历的元素 n 出现的次数后,存入 result;在双层 for 遍历完成后,返回 result 即可

代码实现

var smallerNumbersThanCurrent = function(nums) {
    let map = {};
    nums.forEach(n => map[n] = (map[n] || 0) + 1)
    let arr = Object.keys(map).sort((a, b) => a - b);
    let result = [];
    nums.forEach(n => {
        let sum = 0;
        for (let i = 0; i < arr.length && arr[i] < n; i++) {
            sum += map[arr[i]]
        }
        result.push(sum);
    })
    return result;
};

image.png

优化

上面的解法,性能存在一点瑕疵。阅读源码发现使用了 2 次 forEach,修改为原始的 for 遍历后,性能提升不少

var smallerNumbersThanCurrent = function(nums) {
    let map = {};
    for (let i = 0; i < nums.length; i++) {
        map[nums[i]] = (map[nums[i]] || 0) + 1
    }
    let arr = Object.keys(map).sort((a, b) => a - b);
    let result = [];
    for (let j = 0; j < nums.length; j++) {
        let sum = 0;
        for (let i = 0; i < arr.length && arr[i] < nums[j]; i++) {
            sum += map[arr[i]]
        }
        result.push(sum);
    }
    return result;
};

image.png