当前位置: 首页 > ai >正文

Swift 解锁 LeetCode 热门难题:不改数组也能找出重复数字?

在这里插入图片描述
在这里插入图片描述

文章目录

    • 摘要
    • 描述
    • 题解答案
    • 题解代码分析
      • 解读:
    • 示例测试及结果
    • 时间复杂度
    • 空间复杂度
    • 总结
    • 实际场景类比
    • 可运行 Demo(Swift Playground)
    • 未来展望

摘要

在数组中找出唯一的重复数字,听起来像一道简单的题目,但如果你不能修改原数组、不能使用额外空间,挑战就变得很有意思了。本文通过 Swift 实现 LeetCode 第 287 题《寻找重复数》的题解,并结合实际编码场景详细拆解背后的逻辑推理过程,帮你真正掌握这道经典的算法题。

描述

题目要求你在一个包含 n + 1 个整数的数组中找到一个重复的数。这些数的取值范围是 [1, n],而且保证 只有一个数字重复,可能重复多次

但它还加了一些限制:

  • 数组不能修改(也就是只读)
  • 空间复杂度得是常数级 O(1)
  • 尽可能做到时间复杂度为线性 O(n)

看起来挺棘手?别急,下面我们一步一步来拆解。

题解答案

常见的思路有三种:

  1. 暴力法 / 哈希法(不能用,违反空间复杂度)
  2. 排序 + 遍历(不能用,违反不能修改数组)
  3. 快慢指针(可以用,经典的“链表找环”变体)

我们要用的是第三种方法,也叫 Floyd 判圈算法。

思路是把数组元素看成指针,nums[i] 代表指向下一个元素的索引,就像一个链表。如果有重复数字,就一定会有一个“环”。

题解代码分析

func findDuplicate(_ nums: [Int]) -> Int {var slow = nums[0]var fast = nums[0]// 第一阶段:找相遇点repeat {slow = nums[slow]fast = nums[nums[fast]]} while slow != fast// 第二阶段:找入口(重复的数字)slow = nums[0]while slow != fast {slow = nums[slow]fast = nums[fast]}return slow
}

解读:

  • 第一次 while 循环找的是两个指针在环里相遇的那个位置。我们先从 nums[0] 开始,slow 每次走一步,fast 每次走两步,像跑圈一样,最终肯定会在环里相遇。
  • 第二次 while 循环是经典的“找环入口”,我们让一个指针从开头出发,另一个从相遇点出发,每次走一步,再次相遇的点就是重复数字。

示例测试及结果

let test1 = [1, 3, 4, 2, 2]
print(findDuplicate(test1))  // 输出: 2let test2 = [3, 1, 3, 4, 2]
print(findDuplicate(test2))  // 输出: 3let test3 = [3, 3, 3, 3, 3]
print(findDuplicate(test3))  // 输出: 3

无论重复的是谁,只要有重复,这个算法就能找出来,效率也很高。

时间复杂度

  • 整体是 O(n),因为我们最多只跑两次遍历,而且每次最多走 n 步。

空间复杂度

  • O(1),只用了两个变量 slowfast,没有开任何额外空间。

总结

这题乍一看像是“简单查重”,实则考验对链表结构与指针遍历逻辑的理解。如果你碰到限制不能修改数组、不能用额外空间的情况,这种借助“指针构造隐含链表”的技巧就非常值得掌握。

而且这种技巧在很多系统设计里也很实用,比如检测日志流的循环引用、追踪用户路径中的重复操作等等。

实际场景类比

想象一下你在做用户路径分析,用户访问路径用数组表示 [页面1, 页面2, 页面3, 页面2, 页面4],你希望知道哪个页面用户又返回访问了。

你不能改动原始日志(只读),也不能复制一份数据再做处理(节省内存),这时候就可以考虑类似的“快慢指针找环”方式来识别重复跳转的路径。

可运行 Demo(Swift Playground)

import Foundationfunc findDuplicate(_ nums: [Int]) -> Int {var slow = nums[0]var fast = nums[0]repeat {slow = nums[slow]fast = nums[nums[fast]]} while slow != fastslow = nums[0]while slow != fast {slow = nums[slow]fast = nums[fast]}return slow
}let sample = [1, 4, 6, 2, 5, 3, 6]
print("重复数字是:\(findDuplicate(sample))")

未来展望

这个题是很多“限制场景下查重”的代表题,我们可以往更复杂的方向去探索:

  • 如何在海量数据(分布式系统)中查找重复?
  • 如果有多个重复的数字,又该如何扩展这类算法?
  • Swift 中的指针式遍历,还有哪些地方能发挥类似作用?
http://www.xdnf.cn/news/9807.html

相关文章:

  • Nacos 配置管理案例:nacos-spring-cloud-config-example详解
  • IPD的基础理论与框架——(四)矩阵型组织:打破部门壁垒,构建高效协同的底层
  • django项目开启debug页面操作有数据操作记录
  • 首发支持! 基于昇腾MindIE玩转InternVL3多模态理解最新模型
  • 工具识别系统Python+深度学习+人工智能+卷积神经网络算法+TensorFlow+图像识别
  • ppt一键制作:ai自动生成PPT,便捷高效超级精美!
  • 全志F1c200开发笔记——移植Debian文件系统
  • 彻底卸载安装的虚拟机VMware Workstation软件
  • 树莓派超全系列教程文档--(51)如何使用SSH登录树莓派
  • RFID综合项目实训 | 基于C#的一卡通管理系统
  • AI绘画提示词:从零开始掌握Prompt Engineering的艺术
  • 群辉(synology)NAS老机器连接出现网页端可以进入,但是本地访问输入一样的账号密码是出现错误时解决方案
  • ST MCU CAN模块--TTCAN模式浅析
  • window 显示驱动开发-转换 Direct3D 固定函数状态(一)
  • 界面开发框架DevExpress XAF实践:集成.NET Aspire后如何实现自定义遥测?
  • Odoo 打印功能架构与工作流程深度剖析
  • 什么是node.js、npm、vue
  • 洛谷 P1157:组合的输出 ← dfs
  • 简单三步FastAdmin 开源框架的安装
  • 如何将图像插入 PDF:最佳工具比较
  • 45. 跳跃游戏 II
  • Vue-05(自定义事件)
  • 汽车售后诊断数据流详细分析
  • linux 安装python
  • 性能测试工具选型指南
  • 二级域名怎么申请?二级域名申请费免费吗?
  • Android Studio 解决报错 not support JCEF 记录
  • 【C/C++】chrono简单使用场景
  • 国密SSL证书有哪些技术优势?
  • 基于qt5和stk10开发的互联调试