找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0 ~ n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
示例:
1输入:[2, 3, 1, 0, 2, 5, 3]
2输出:2 或 3从题目中分析,只需要找到任意一个重复的数字,那么可以利用哈希表,用数字的值作为 key 去存储,如果遇到已经存在的 key,则直接返回,这样就找到了重复的数字。
声明哈希表用来保存遍历的值。
开始遍历数组。
获取当前值,判断值是否已经存在,若存在,则返回结果并结束循环;若不存在,则继续下一步。
储存当前值进哈希表。
处理数组下一位,重复直到遍历完成。
1/**
2 * @param {number[]} nums
3 * @return {number}
4 */
5const findRepeatNumber = function (nums) {
6 // 定义 hash 表
7 let map = new Map();
8 let i = 0;
9 while (i < nums.length) {
10 // 如果存在当前数字,那么直接结束循环,返回当前数字
11 if (map.has(nums[i])) {
12 return map.get(nums[i]);
13 }
14 // 储存已经遍历过的值
15 map.set(nums[i], nums[i]);
16 i++;
17 }
18};时间复杂度 O(N):遍历一遍数组既可完成。
空间复杂度 O(N):需要声明哈希表进行存储。
我们可以把数组的值,交换到与该值相等的索引的位置。如果交换时发现,该索引的位置已经存在与当前值相等的值,则结束操作并返回当前值。
遍历数组。
判断当前值和索引是否相等,如果是,直接跳过处理下一个元素,不是,则进行下一步。
判断需要交换的索引位置的值,是否和当前值相等,如果是,则返回当前值并结束,不是,则进行下一步。
将当前值和对应索引位置的元素进行交换。
依次处理完全部元素。
1/**
2 * @param {number[]} nums
3 * @return {number}
4 */
5const findRepeatNumber = function (nums) {
6 let i = 0;
7 while (i < nums.length) {
8 // 如果当前值等于索引,那么直接跳过
9 if (nums[i] === i) {
10 i++;
11 continue;
12 }
13 // 如果需要交换的索引位置已经存在相同值,直接结束,返回当前值
14 if (nums[nums[i]] === nums[i]) {
15 return nums[i];
16 }
17 // 交换当前值,和对应索引存在的值
18 [nums[nums[i]], nums[i]] = [nums[i], nums[nums[i]]];
19 }
20 return -1;
21};时间复杂度 O(N):每个元素最多被移动 2 次。
空间复杂度 O(1):不需要额外的空间完成。