leetcode hot100之寻找重复数(287)解析

141 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第31天,点击查看活动详情


前言

  • leetcode hot100,是大厂面试高频题,也是必刷算法题。精选了100道LeetCode上最热门的题目,适合初识算法与数据结构的新手和想要在短时间内高效提升的人,按照官方说的,熟练掌握这 100 道题,就具备了代码世界通行的基本能力。

leetcode287题(# 寻找重复数

本文来讲hot100第287题(寻找重复数),本题有三种解法,二进制、二分查找、快慢指针,我们本篇文章使用快慢指针来讲。

给定一个包含 n + 1 个整数的数组 nums ,其数字都在 [1, n] 范围内(包括 1 和 n),可知至少存在一个重复的整数。

假设 nums 只有 一个重复的整数 ,返回 这个重复的数 。

你设计的解决方案必须 不修改 数组 nums 且只用常量级 O(1) 的额外空间。

示例:

输入: nums = [1,3,4,2,2]
输出: 2
输入: nums = [3,1,3,4,2]
输出: 3

提示:

  • 1 <= n <= 105
  • nums.length == n + 1
  • 1 <= nums[i] <= n
  • nums 中 只有一个整数 出现 两次或多次 ,其余整数均只出现 一次

进阶:

  • 如何证明 nums 中至少存在一个重复的数字?
  • 你可以设计一个线性级时间复杂度 O(n) 的解决方案吗?

分析

  • 数组的数组范围为[1, n]
  • 数组存在一个重复的整数,可能出现多次
  • 要求不修改数组nums切使用O(1)的额外空间

思路

  • 我们可以使用快慢指针来解决,与141/142题环形列表的题目方法一样。
  • 由于存在重复的数字,那么目标至少数字有2个指向它的边,那么整个数组一定会形成一个环
  • 所以我们要找到的环的入口,找到了入口也就找到了重复的数字
  • 设一个慢指针,一个快指针,慢指针每次走一步,快指针每次走二步,
  • 当2个指针相遇,我们再将慢指针放到起点0,2个指针每次同时移动一步,相遇的点就是答案

代码

  let slow = 0,
    fast = 0;
  do {
    slow = nums[slow];
    fast = nums[nums[fast]];
  } while (slow != fast);
  slow = 0;
  while (slow != fast) {
    slow = nums[slow];
    fast = nums[fast];
  }
  return slow;

结语

快慢指针时间复杂度O(n),空间复杂度O(1)