持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情
每日刷题 2022.06.04
- leetcode原题链接:leetcode.cn/problems/n-…
- 难度:简单
- 方法:数学、map、概率
题目
- 给你一个整数数组 nums ,该数组具有以下属性:
- nums.length == 2 * n.
- nums 包含 n + 1 个 不同的 元素
- nums 中恰有一个元素重复 n 次
- 找出并返回重复了 n 次的那个元素。
示例
- 示例1
输入: nums = [1,2,3,3]
输出: 3
- 示例2
输入: nums = [2,1,2,5,3,2]
输出: 2
- 示例3
输入: nums = [5,1,5,2,5,3,5,4]
输出: 5
提示
- 2 <= n <= 5000
- nums.length == 2 * n
- 0 <= nums[i] <= 10^4
- nums 由 n + 1 个 不同的 元素组成,且其中一个元素恰好重复 n 次
解题思路
nums中恰有一个元素重复n次,返回重复了n次的元素。第一时间想到的就是map集合统计计数,因为数组给的范围也很小。
拓展(random)
Math.floor(Math.random() * (max - min + 1)) + min; //含最大值,含最小值
Math.floor(Math.random() * (max - min)) + min; //不含最大值,含最小值
简单的map集合
- (无脑
map)直接记录整个数组中每个数重复出现的次数,当遇到一个元素出现了n次,那么就返回这个数。 - 后续分析:
map做法还可以优化,也就是找到两个是相同的就可以返回。- 因为题目中说了:长度是2 * n,并且有n + 1个不同的数,且存在n个数是相同的,也就是说除了n个相同的数以外,剩下的所有的数都是不同的
AC代码
/**
* @param {number[]} nums
* @return {number}
*/
var repeatedNTimes = function(nums) {
let map = new Map();
const n = nums.length, half = n / 2;
// 记录数组中的每一个数出现的次数
for(let i = 0; i < n; i++) {
map.set(nums[i], (map.get(nums[i]) || 0) + 1);
// 当遇到当前数在数组中的出现次数等于half,那么就返回
if(map.get(nums[i]) == half) {
return nums[i];
}
}
};
数学
- 推导一下:那么当n > 2时的最大间隔是多少?最小间隔是多少?
- n >= 2时,最大间隔是2个,最小间隔是0个
- 因此对于当前的元素,只需要依次往后找3个进行判断即可
AC代码
- 数学解法
/**
* @param {number[]} nums
* @return {number}
*/
var repeatedNTimes = function(nums) {
const n = nums.length;
for(let i = 0; i < n; i++) {
// 分别判断,当前的数和间隔为0的数是否相等
// 当前的数和间隔为1的数是否相等
// 当前的数和间隔为2的数是否相等
// 同时还要保证下标不会越界
if((i + 1 < n && nums[i] == nums[i + 1]) || (i + 2 < n && nums[i] == nums[i + 2]) || (i + 3 < n && nums[i] == nums[i + 3])){
return nums[i];
}
}
};
概率做法
- 根据上述的分析,我们知道数组中只有1个数是可以重复的,且其重复了
n次,那么现在只需要找到两个数相同就可以找到答案。 - 在整个数组中,取到两个数相同的概率:
(n / 2n) * (n - 1 / 2n) 约等于 1 / 4- 也就是说最好的情况下,我们随机选择
4次就可以找到两个相同的数,但是也有可能比4次大。 - 但是其始终是常熟级别的
o(4) = o(1)
- 也就是说最好的情况下,我们随机选择
AC代码
/**
* @param {number[]} nums
* @return {number}
*/
var repeatedNTimes = function(nums) {
// 随机选择法
const n = nums.length;
while(true) {
// 随机生成需要比较的两个下标
const x = Math.floor(Math.random() * (n));
const y = Math.floor(Math.random() * (n));
// 随机生成有可能生成两个相同的数,但是不能自己和自己比较,因此需要排除x == y的情况
if(x != y && nums[x] == nums[y]) return nums[x];
}
};