前言
滴,算法卡~
今天继续围绕数组专题做题,还是选择了一道简单程度的数组题目。
今日题目
leecode地址:剑指 Offer 03. 数组中重复的数字
找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
示例:
输入: [2, 3, 1, 0, 2, 5, 3] 输出:2 或 3
限制:
2 <= n <= 100000
解题思路
思路一:
拿到这道题目我第一个想到的就是创建一个数组的方式:
声明一个临时数组,遍历nums,如果数字不存在临时数组中,说明是没出现过的数字,则放到临时数组中;如果在临时数组中已经存在该数字,就是我们要找的重复数字,直接返回该数字。
var findRepeatNumber = function(nums) {
let temp = []
let idx = 0
for(let i = 0; i< nums.length; i++) {
if (temp.indexOf(nums[i]) === -1) {
temp.push(nums[i])
} else {
idx = i
break
}
}
return nums[idx]
};
但是太慢了,结果很不理想。。。时间复杂度是 O(n),空间复杂度是 O(n)
思路二:原地置换法
由于题目要求数组长度为n,并且数字在0 ~ n - 1之间,正好是长度为n的数组的下标一致,假设数组中没有重复数字,那么每个数字应该排序后与其下标一一对应。
那么我们将数组进行置换,每一个数字应该与其在数组中下标相同,比如nums[2] = 2,如果发现当前位置的数字无法换出去,那就说明已经存在了,那就是我们要找的重复数字了。
var findRepeatNumber = function(nums) {
let i = 0
while(i < nums.length){
let target = nums[i]
if (target !== i) {
if (nums[target] === nums[i]) {
return nums[i]
}
let temp = nums[target]
nums[target] = nums[i]
nums[i] = temp
} else {
i++
}
}
};
换了这种思路后,用时明显缩短,
时间复杂度是 O(n),空间复杂度是 O(1)
思路三: 利用Set结构不可重复特性
看了题解,有人是利用Set结构的不可重复性,遍历数组放到Set中,如果发现Set.size不变,说明放进去的是重复的数字
var findRepeatNumber = function(nums) {
let set = new Set()
for(let i = 0; i < nums.length; i++) {
const lastSize = set.size
set.add(nums[i])
if (set.size === lastSize) {
return nums[i]
}
}
};
总结
本题主要使用原地置换法,我拿到题目第一瞬间想不到这个方法,是我看了题解的思路之后才想到的。 3月第三天,我的出走计划还有好多来不及做,有点着急,whatever,继续努力吧!!!
本文正在参与「掘金 2021 春招闯关活动」, 点击查看 活动详情