数组中重复的数据
难度:
标签:
题目描述
给你一个长度为 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 <= 105
1 <= nums[i] <= n
nums
中的每个元素出现 一次 或 两次
代码结果
运行时间: 41 ms, 内存: 23.9 MB
/*
* 题目思路:
* 给定一个长度为 n 的整数数组 nums,其中 nums 的所有整数都在范围 [1, n] 内,且每个整数出现一次或两次。
* 要求找出所有出现两次的整数,并以数组形式返回。设计一个时间复杂度为 O(n) 且仅使用常量额外空间的算法。
*
* 解题思路:
* 使用 Java Stream 实现上述逻辑
*/
import java.util.*;
import java.util.stream.*;
public class Solution {
public List<Integer> findDuplicates(int[] nums) {
List<Integer> result = new ArrayList<>();
IntStream.range(0, nums.length).forEach(i -> {
int index = Math.abs(nums[i]) - 1;
if (nums[index] < 0) {
result.add(Math.abs(nums[i]));
} else {
nums[index] = -nums[index];
}
});
return result;
}
}
解释
方法:
该题解采用了一个巧妙的方法来在原地标记数组中已经访问过的数字,利用数组元素的符号进行标记。具体步骤如下:
1. 遍历数组中的每一个元素。
2. 使用当前元素的绝对值减一得到数组的索引位置 `idx`。
3. 检查位于 `idx` 的元素的符号。
- 如果该位置的元素为负数,说明之前已经访问过该位置,因此当前数字是重复的,将其加入结果列表。
- 如果该位置的元素为正数,将其变为负数,表示该位置已被访问过。
4. 遍历完成后,结果列表中的元素即为出现两次的数字。
时间复杂度:
O(n)
空间复杂度:
O(1)
代码细节讲解
🦆
在算法中,若数组中存在大于两次的重复数字,此方法能否正确处理并只返回两次的重复数字?
▷🦆
为什么在处理完整个数组后,没有将数组中的元素恢复到原始状态?这样做会对原数组产生什么影响?
▷🦆
在算法中使用元素的符号作为访问标记,这种方法在处理非整数或超出[1,n]范围的数字时是否还适用?
▷