51mee - AI智能招聘平台Logo
模拟面试题目大全招聘中心会员专区

给定一个长度为n+1的数组,其中包含1到n的整数,但数组中有一个数字重复出现。请设计一个算法,找出这个重复的数字,要求时间复杂度O(n),空间复杂度O(1)(不使用额外数组或哈希表)。请说明算法思路和实现步骤。

Tencent软件开发-移动客户端开发方向难度:中等

答案

1) 【一句话结论】

可以用 Floyd 判圈算法(龟兔赛跑)解决,通过模拟数组的循环链表结构,找到环的入口即为重复的数字,时间复杂度 O(n),空间复杂度 O(1)。

2) 【原理/概念讲解】

Floyd 判圈算法的核心是将数组视为一个循环链表:

  • 数组元素值为 1~n,索引从 0 开始,因此元素值为 k 的节点,其下一个节点索引为 k-1(即 arr[k-1])。
  • 当数组存在重复数字时,链表会形成环(例如,元素值为 3 的节点指向索引 2,而索引 2 的元素值也为 3,导致环)。

通过快慢指针(慢指针每次走 1 步,快指针每次走 2 步)检测环:

  • 若存在环,快指针会先追上慢指针(第一次相遇点)。
  • 之后,从起点(慢指针重新指向 0)和相遇点(快指针位置)同时出发,再次相遇的点即为环的入口(重复数字)。

类比:想象一群人在跑圈,慢跑的人(慢指针)和快跑的人(快指针),若圈上有入口(环),快跑的人会先追上慢跑的人,然后从起点和相遇点同时出发,再次相遇的位置就是入口(重复数字)。

3) 【对比与适用场景】

方法定义时间复杂度空间复杂度适用场景注意点
Floyd判圈法将数组视为循环链表,用快慢指针找环入口O(n)O(1)数组长度 n+1,元素 1~n,有重复需数组至少有一个重复,元素值在 1~n
排序后找相邻重复先排序数组,再检查相邻元素是否相等O(n log n)O(1)(原地排序)或 O(n)(复制数组)空间要求严格时时间复杂度较高,不满足 O(n)
哈希表法用哈希表记录每个数字是否出现过O(n)O(n)空间允许时空间复杂度不符合题目要求

4) 【示例】

数组 arr = [3,1,3,4,2](长度 5+1=6,数字 1~4,重复 3):

  • 初始化:慢指针 slow=0,快指针 fast=0。
  • 循环移动指针:
    • slow = arr[0]=3 → slow=2;
    • fast = arr[arr[0]]=arr[3]=4 → fast=4;
    • slow = arr[2]=3 → slow=2;
    • fast = arr[arr[4]]=arr[2]=3 → fast=3;
    • slow = arr[2]=3 → slow=2;
    • fast = arr[arr[3]]=arr[4]=2 → fast=2;
    • 此时 slow=fast=2,第一次相遇(值为 3?不对,实际相遇在索引 2,值为 3,正确)。
  • 重新初始化:慢指针 slow=0,快指针 fast=arr[0]=3。
  • 再次循环:
    • slow = arr[0]=3 → slow=2;
    • fast = arr[arr[3]]=arr[4]=2 → fast=2;
    • slow = arr[2]=3 → slow=2;
    • fast = arr[arr[2]]=arr[3]=4 → fast=4;
    • 此时 slow=fast=2,相遇(值为 3),即重复数字。

5) 【面试口播版答案】

面试官您好,这个问题可以用 Floyd 判圈算法(龟兔赛跑算法)解决。核心思路是将数组视为一个循环链表,每个元素的值作为下一个节点的索引(因为数组元素是 1~n,索引从 0 开始,所以元素值为 k 的节点指向索引 k-1)。当存在重复数字时,链表形成环。用快慢指针检测环:慢指针每次走 1 步,快指针每次走 2 步,直到两者相遇。相遇后,重新初始化慢指针为 0,快指针指向数组第一个元素(索引 0),再次移动直到相遇,此时的值就是重复的数字。具体步骤:1. 初始化慢指针 slow 和快指针 fast 都指向数组第一个元素(索引 0);2. 循环移动指针,直到 slow == fast;3. 重新初始化 slow=0,fast=arr[0];4. 再次循环直到 slow == fast,结果即为重复数字。时间复杂度 O(n),空间复杂度 O(1),满足题目要求。

6) 【追问清单】

  1. 如果数组中重复数字出现多次,算法是否还能正确找到?
    回答:是的,因为环的入口就是重复数字,即使重复多次,环的入口不变。
  2. 如果数组长度为 n,元素是 0~n-1,是否适用?
    回答:需要调整索引映射,将数组值作为索引(即元素值为 k,下一个节点是索引 k),此时算法同样适用。
  3. 算法是否需要数组中至少有一个重复数字?
    回答:是的,否则不会形成环,无法检测。
  4. 如果数组中存在负数或非 1~n 的数字,是否还能用?
    回答:需要先处理数组,比如将所有数字调整到 1~n 范围内(例如,将负数加 n+1),再应用算法。
  5. 时间复杂度分析是否正确?
    回答:快慢指针的移动次数最多为 n 次,所以时间复杂度是 O(n),空间复杂度 O(1)。

7) 【常见坑/雷区】

  1. 忽略数组长度为 n+1,直接用哈希表或排序,导致空间或时间复杂度不符合题目要求。
  2. 指针初始化错误,比如快指针初始为 0,慢指针为 0,移动后错过环的入口。
  3. 环入口判断错误,第一次相遇后没有重新初始化指针再找入口。
  4. 索引映射错误,比如数组元素值是 1~n,但错误地认为索引是元素值本身,导致链表构建错误。
  5. 时间复杂度分析错误,认为循环次数是 n²,实际上快慢指针的步数是 O(n),所以是 O(n)。
51mee.com致力于为招聘者提供最新、最全的招聘信息。AI智能解析岗位要求,聚合全网优质机会。
产品招聘中心面经会员专区简历解析Resume API
联系我们南京浅度求索科技有限公司admin@51mee.com
联系客服
51mee客服微信二维码 - 扫码添加客服获取帮助
© 2025 南京浅度求索科技有限公司. All rights reserved.
公安备案图标苏公网安备32010602012192号苏ICP备2025178433号-1