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

寻找重复数 - LeetCode 287 题解笔记

寻找重复数 - LeetCode 287 题解笔记

问题描述

给定一个包含 n + 1 个整数的数组 nums,其数字都在 [1, n] 范围内(包括 1 和 n),已知至少存在一个重复的整数。假设 nums 只有一个重复的整数,返回这个重复的数。

要求

  • 不修改数组 nums
  • 只使用常量级 O(1) 的额外空间

解题思路

方法一:快慢指针法(Floyd判圈算法)

核心思想

将数组视为链表,利用快慢指针检测环的存在并找到环的入口:

  1. 数组映射为链表

    • 索引作为节点
    • 数组值作为指向下一个节点的指针
  2. 重复数字必然形成环

    • 因为多个索引指向同一个值
    • 例如 nums = [1,3,4,2,2] → 0→1→3→2→4→2→4→…(在2和4之间形成环)
算法步骤
  1. 第一阶段:检测环

    • 快指针每次走两步,慢指针每次走一步
    • 当两者相遇时,确认存在环
  2. 第二阶段:找到环入口

    • 将慢指针重置到起点
    • 快慢指针改为每次各走一步
    • 再次相遇点即为重复数字
class Solution {
    public int findDuplicate(int[] nums) {
        // 初始都从第一个元素开始
        int slow = nums[0];
        int fast = nums[0];
        
        // 第一阶段:找到相遇点
        do {
            slow = nums[slow];
            fast = nums[nums[fast]];
        } while (slow != fast);
        
        // 第二阶段:找到环的入口
        slow = nums[0];
        while (slow != fast) {
            slow = nums[slow];
            fast = nums[fast];  // 这里应该是单步移动,不是双步
        }
        
        return slow;
    }
}
复杂度分析
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

方法二:二分查找法

核心思想

利用抽屉原理进行二分查找:

  1. 数值范围二分

    • 在[1,n]范围内二分
    • 统计小于等于mid的数的个数
  2. 调整搜索范围

    • 如果计数 > mid,说明重复数在左半区
    • 否则在右半区
class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int n = nums.size();
        int l = 1, r = n - 1, ans = -1;
        while (l <= r) {
            int mid = (l + r) >> 1;
            int cnt = 0;
            for (int i = 0; i < n; ++i) {
                cnt += nums[i] <= mid;
            }
            if (cnt <= mid) {
                l = mid + 1;
            } else {
                r = mid - 1;
                ans = mid;
            }
        }
        return ans;
    }
};
复杂度分析
  • 时间复杂度:O(n log n)
  • 空间复杂度:O(1)

关键点说明

  1. 为什么快慢指针能工作

    • 重复数字导致多个节点指向同一个节点
    • 形成环后,快指针最终会追上慢指针
  2. 边界条件处理

    • 数组长度至少为2(因n≥1)
    • 保证只有一个重复数字
  3. 与常规链表环检测的区别

    • 不需要实际构建链表
    • 直接利用数组索引和值的映射关系

相关文章:

  • Linux 系统检测进程死锁的方法
  • 今日 GitHub 热门项目大赏,你 pick 谁?
  • 4.go语言数组
  • 1.1 计算机网络的概念
  • 基于python的4个小游戏(免费直接使用)
  • LLaMA-Factory使用实战
  • Fiddler抓取HTTPS
  • Python中的Requests库
  • 使用VSCODE导致CPU占用率过高的处理方法
  • 【力扣hot100题】(001)字母异位词分组
  • Java 并发编程面经
  • RK3588,V4l2 读取Gmsl相机, Rga yuv422转换rgb (mmap)
  • 港中文迈向安全的具身AI!EARBench:基础模型在具身AI任务规划中的物理风险评估
  • Pytorch--tensor.view()
  • VSCode Flutter 快捷键
  • swagger上传图片请求报错
  • 【嵌入式硬件测试之道连载之第五章:嵌入式硬件接口测试】
  • 我的创作纪念日——三周年
  • leetcode_字符串 3. 无重复字符的最长子串
  • 解决GitLab无法拉取项目
  • 深圳房地产信息网官方网站/今日国际重大新闻
  • 网站开发模板带css样式/百度关键词优化排名
  • 手机网站集成支付宝/app如何推广
  • 诸城网站建设定制/seo外包大型公司
  • 给别人做网站如何收费/代写文案平台
  • 网站制作步骤是什么/东莞今日头条新闻