一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第 4 天,点击查看活动详情。
题目链接
1365. 有多少小于当前数字的数字 - 力扣(LeetCode) (leetcode-cn.com)
题目描述
给你一个数组 nums,对于其中每个元素 nums[i],请你统计数组中比它小的所有数字的数目。
换而言之,对于每个 nums[i] 你必须计算出有效的 j 的数量,其中 j 满足 j != i 且 nums[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;
};
优化
上面的解法,性能存在一点瑕疵。阅读源码发现使用了 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;
};