442. 数组中重复的数据
题目来源
题目分析
给你一个长度为
n的整数数组nums,其中nums的所有整数都在范围[1, n]内,
且每个整数最多出现两次。请你找出所有出现两次的整数,并以数组形式返回。
题目难度
- 难度:中等
题目标签
- 标签:数组、哈希表
题目限制
n == nums.length1 <= n <= 10^51 <= nums[i] <= nnums中的每个元素出现一次或两次
解题思路
思路:原地哈希法
- 问题定义:
- 需要找出数组中所有出现两次的整数。
- 核心算法:
- 利用数组本身作为哈希表,通过交换元素,使得每个数字都放置在其对应的索引位置上。
- 遍历数组,如果当前元素不在其正确的位置上,则交换它到正确的位置。
- 再次遍历数组,那些位置不正确的元素即为出现两次的元素。
- 关键步骤:
- 遍历数组,对于每个元素,如果它不在正确的位置上,则进行交换。
- 再次遍历数组,找出那些位置不正确的元素。
核心算法步骤
- 初始化结果列表:
- 创建一个
ArrayList<Integer>类型的列表ans,用于存储出现两次的整数。
- 创建一个
- 原地哈希交换:
- 遍历数组,对于每个元素
nums[i],如果它不在位置nums[i] - 1上,则与nums[nums[i] - 1]交换。 - 继续交换,直到所有元素都在正确的位置上或者遇到一个已经放置正确的元素。
- 遍历数组,对于每个元素
- 找出重复元素:
- 再次遍历数组,如果元素
nums[i]不在位置i + 1上,则它就是出现两次的元素,将其添加到结果列表ans中。
- 再次遍历数组,如果元素
- 返回结果:
- 返回列表
ans。
- 返回列表
代码实现
以下是原地哈希法的 Java 代码实现:
public List<Integer> findDuplicates(int[] nums) {
List<Integer> ans = new ArrayList<>();
for (int i = 0; i < nums.length; i++) {
while (nums[i] != nums[nums[i] - 1]) {
int temp = nums[i];
nums[i] = nums[temp - 1];
nums[temp - 1] = temp;
}
}
for (int i = 0; i < nums.length; i++) {
if (nums[i] != i + 1) {
ans.add(nums[i]);
}
}
return ans;
}
代码解读
- 原地哈希交换:通过交换元素,使得每个数字都放置在其对应的索引位置上。
- 找出重复元素:再次遍历数组,那些位置不正确的元素即为出现两次的元素。
性能分析
- 时间复杂度:
O(n),每个元素最多只需要交换两次就能到达正确的位置。 - 空间复杂度:
O(1),除了输入数组外,不需要额外的存储空间。
总结
该方法通过原地哈希的思想,将每个数字放置到其对应的索引位置上,从而找出所有出现两次的整数。这种方法既高效又节省空间,适用于大规模数据。在实际应用中,是一种非常实用的算法技巧。

1061

被折叠的 条评论
为什么被折叠?



