给你一个整数数组 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] <= 104
- nums 由 n + 1 个 不同的 元素组成,且其中一个元素恰好重复 n 次
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/n-repeated-element-in-size-2n-array
题解:
这个题第一反应是计数,但这个数出现第二次就可以进行输出,但是用数组存储数出现的次数,就会造成空间上的浪费;官方使用了hashmap的方式来进行数出现次数的计数(对这种不熟练,要熟练并灵活运用!!)
还有种方法是通过比较的方式进行寻找:数组中有N个非重复元素和N个重复元素,无论N个重复元素如何均匀地分布在总共2N个元素中,总能找到长度为4的连续子序列中至少有2个重复元素。
(官方)一旦找到一个重复元素,那么一定就是答案。我们称这个答案为主要元素。
考虑所有长度为 4 的子序列,在子序列中一定至少含有两个主要元素。
这是因为:
长度为 2 的子序列中都是主要元素,或者;
每个长度为 2 的子序列都恰好含有 1 个主要元素,这意味着长度为 4 的子序列一定含有 2 个主要元素。
因此,只需要比较所有距离为 1,2 或者 3 的邻居元素即可。
class Solution {
public int repeatedNTimes(int[] nums) {
int result = 0;
int[] numCount = new int[10001];
for(int i = 0;i < nums.length;i++){
numCount[nums[i]]++;
if(numCount[nums[i]] > 1){
result = nums[i];
break;
}
}
return result;
}
}
class Solution {
public int repeatedNTimes(int[] nums) {
Map<Integer, Integer> count = new HashMap();
for (int x: nums) {
count.put(x, count.getOrDefault(x, 0) + 1);
}
for (int k: count.keySet())
if (count.get(k) > 1)
return k;
throw null;
}
}
class Solution {
public int repeatedNTimes(int[] nums) {
for (int k = 1; k <= 3; ++k)
for (int i = 0; i < nums.length - k; ++i)
if (nums[i] == nums[i+k])
return nums[i];
throw null;
}
}