题目
给你一个长度为 n 的整数数组 nums ,其中 nums 的所有整数都在范围 [1, n] 内,且每个整数出现 最多两次 。
请你找出所有出现 两次 的整数,并以数组形式返回。
你必须设计并实现一个时间复杂度为 O(n) 且仅使用常量额外空间(不包括存储输出所需的空间)的算法解决此问题。
示例 1:
输入:nums = [4,3,2,7,8,2,3,1] 输出:[2,3] 示例 2:
输入:nums = [1,1,2] 输出:[1] 示例 3:
输入:nums = [1] 输出:[]
提示:
n == nums.length 1 <= n <= 10^5 1 <= nums[i] <= n nums 中的每个元素出现 一次 或 两次
v1-HashMap
说明:v1+v2 都使用了额外的存储空间,不满足题目条件。但是思路还是统一放出来。
思路
通过 HashMap 存储每一个元素出现的次数。
实现
public List<Integer> findDuplicates(int[] nums) {
List<Integer> list = new ArrayList<>();
Map<Integer, Integer> map = new HashMap<>();
for(int num : nums){
int count = map.getOrDefault(num, 0);
if(count > 0) {
list.add(num);
}
map.put(num, count+1);
}
return list;
}
效果
23ms 10.80%
效果一般
小结
思路不算难 Hash 在这个系列的适用性特别广。
其实这个复杂度就是 O(n)
V2-HashSet
区别
唯一的区别就是唯一的数据可能重复,所以有重复的我们放入结果列表后移除即可。或者不放入也行。
代码
public List<Integer> findDuplicates(int[] nums) {
List<Integer> list = new ArrayList<>();
Set<Integer> set = new HashSet<>();
for(int num : nums){
if(set.contains(num)) {
list.add(num);
}
set.add(num);
}
return list;
}
效果
19ms 12.68%
v3-排序的思路
思路
很自然的想到,比较我们应该先做一个排序。
然后再比较,和下一个相等就存在。
代码
class Solution {
public List<Integer> findDuplicates(int[] nums) {
List<Integer> list = new ArrayList<>(nums.length);
Arrays.sort(nums);
for(int i = 0; i < nums.length-1;i++){
if(nums[i] == nums[i+1]) {
list.add(nums[i]);
}
}
return list;
}
}
效果
18ms 17.37%
效果一般。那么,应该怎么解决呢?
v3-交换思路
看了下解答,很多都是创建了空间,所以速度比较快。
这里选择一种比较有趣的解法
当然这一题目的限制比较多,限制了数组的长度+大小
也就是这一题的特定解法。
交换
数组中的每个整数都在 [1, n] 范围内,因此可以将数组的值与其索引一一对应起来。
通过“交换”的方式,我们将每个元素放到它应该在的位置。具体地,数字 nums[i] 应该放在 nums[i] - 1 的位置。
如果某个元素已经在正确的位置上,我们就不做任何操作;如果它不在正确的位置上,我们就将其交换到正确的位置上。
如果某个数字在正确的位置上发现已经有重复的元素,那就说明它是重复的数字。
实现
public List<Integer> findDuplicates(int[] nums) {
int n = nums.length;
List<Integer> ans = new ArrayList<>();
for (int i = 0; i < n; i++) {
// 不断交换,将 nums[i] 放到 i-1 处,交换到最后,会将重复的数值,放到缺失数值的位置上
while (nums[i] != nums[nums[i] - 1]) swap(nums, i, nums[i] - 1);
}
for (int i = 0; i < n; i++) {
if (nums[i] - 1 != i) ans.add(nums[i]); // 如果 数值 ≠ 位置 + 1,则说明数值是重复的
}
return ans;
}
private void swap(int[] nums, int index1, int index2) {
int temp = nums[index1];
nums[index1] = nums[index2];
nums[index2] = temp;
}