数组「2」数组中重复的数字|刷题打卡

459 阅读2分钟

前言

滴,算法卡~

今天继续围绕数组专题做题,还是选择了一道简单程度的数组题目。

今日题目

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 春招闯关活动」, 点击查看 活动详情