方法一 排序法:
2*n长度的数组里面有一个元素重复了n次,那么将数组排序,求出排序后数组的中间值(因为长度是偶数,没有刚好的中间值,默认求的中间值是偏左边的那个)那么共有三种情况:
- 重复n次的元素为最小值那么数组前一半都是该元素,此时中间值也是该元素
- 重复n次的元素为最大值,那么数组后一半都是该元素,此时中间值后面一个就是该元素
- 既不是最大值也不是最小值,那么中间值也一定就是该元素
var repeatedNTimes = function(nums) {
nums.sort((a,b)=>a-b)
var mid = Math.floor((nums.length-1)/2)
if(nums[mid]===nums[mid-1] || nums[mid]===nums[mid+1])
return nums[mid]
else if(nums[mid+1]===nums[mid+2])
return nums[mid+1]
};
消耗时间和内存情况:
方法二 Map集合
用map记录nums里的各元素各出现了多少次,出现了n次即可返回
var repeatedNTimes = function(nums) {
var len = nums.length/2
var map = new Map()
for(let n of nums){
if(map.has(n)){
map.set(n,map.get(n)+1)
if(map.get(n)===len) return n
}else{
map.set(n,1)
}
}
};
消耗时间和内存情况:
方法三 数学方法:
考虑重复元素x在nums中出现的位置;
如果相邻的x之间至少都隔了2个位置,那么数组的总长度至少为:n+2(n-1)=3*n - 2
当n>2时,3n-2 > 2n 不存在满足要求的数组。因此一定存在两个相邻的x,它们的位置是连续的,或者只隔了1个位置
当n=2时,数组的长度最多为2n=4,因此最多只能隔2个位置。
所以我们只需要遍历所有间隔2个位置及以内的小标对,判断对应的元素是否相等即可
var repeatedNTimes = function(nums) {
const n = nums.length;
for (let gap = 1; gap <= 3; ++gap) {
for (let i = 0; i + gap < n; ++i) {
if (nums[i] === nums[i + gap]) {
return nums[i];
}
}
}
// 不可能的情况
return -1;
};