「这是我参与11月更文挑战的第 15 天,活动详情查看:2021最后一次更文挑战」
原题链接
961. 重复 N 次的元素 - 力扣(LeetCode) (leetcode-cn.com)
题目描述
在大小为 2N 的数组 A 中有 N+1 个不同的元素,其中有一个元素重复了 N 次。
返回重复了 N 次的那个元素。
测试用例
示例 1:
输入:[1,2,3,3]
输出:3
示例 2:
输入:[2,1,2,5,3,2]
输出:2
参数限制
- 4 <= A.length <= 10000
- 0 <= A[i] < 10000
- A.length 为偶数
分析
题目简洁明了,在长度为 2n 的数组中,有一个元素重复了 n,那么我们统计这个数组中各个元素重复出现的次数,只要有一个元素重复的次数达到了 n 次,那么这个数就是我们需要求的数
代码
var repeatedNTimes = function(nums) {
let half = nums.length / 2;
let obj = {};
for (let i = 0; i < nums.length; i++) {
let m = obj[nums[i]] || 0;
if (m == half - 1) return nums[i];
obj[nums[i]] = m + 1;
}
return -1;
};
性能有点拉垮??再读题,数组长度为 2n,其中有 n+1 个元素,有一个元素重复了 n 次,那么,剩下的 n 个元素,占据了数组中的剩余的 n 个位置
换个说法,只要有一个元素重复了 2 次,那么这个数就一定是我们需要查找的数
为了提高检索的效率,我们需要引入一个 Set,每个数字先去 set 里查找,没有则添加到 set, 如果找到了,就说明上一次已经添加了,即已经出现过,这个时候我们直接返回这个数即可
优化
var repeatedNTimes = function(nums) {
let set = new Set();
for (let i = 0; i < nums.length; i++) {
let n = nums[i];
if(set.has(n))return n;
set.add(n);
}
return -1;
};
相比上一种方法,只需要找到重复 2 此的数字即可立即返回,执行的效率就好上很多
扩展
换一个思路,现有 n 个各不相同的数字组成的数组,我们再吧 n 个相同但不同于之前的数字,插入前一步的数组里,理想情况,相同数字直接相邻;次一级的情况,相同数字间隔一个;最次的情况,相同的数字间有 2 个不同的数据,这三种的示例如下:
1, 1, 2, 3
1, 2, 1, 3
1, 2, 3, 1
鉴于这种思路,我们只需要按序获取 4 个相邻的数字,从头往后遍历,就一定能获取到重复的数字,这种方法就可以去掉 set 辅助
今天的力扣刷题就分享到这里,感谢大家的阅读~