前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >287. 寻找重复数

287. 寻找重复数

作者头像
张伦聪zhangluncong
发布2022-10-26 17:59:48
2320
发布2022-10-26 17:59:48
举报

给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。

示例 1:

代码语言:javascript
复制
输入: [1,3,4,2,2]
输出: 2

示例 2:

代码语言:javascript
复制
输入: [3,1,3,4,2]
输出: 3

说明:

代码语言:javascript
复制
不能更改原数组(假设数组是只读的)。
只能使用额外的 O(1) 的空间。
时间复杂度小于 O(n2) 。
数组中只有一个重复的数字,但它可能不止重复出现一次。

解:一种是二分法,然后遍历整个数组计算左边大于mid的数量和左边数的个数是否相同。 一种是龟兔算法快慢指针:

Floyd判圈算法

龟兔算法参考1

龟兔算法参考2

龟兔算法参考3

假设数组中没有重复,那我们可以做到这么一点,就是将数组的下标和1到n每一个数一对一的映射起来。比如数组是213,则映射关系为0->2, 1->1, 2->3。假设这个一对一映射关系是一个函数f(n),其中n是下标,f(n)是映射到的数。如果我们从下标为0出发,根据这个函数计算出一个值,以这个值为新的下标,再用这个函数计算,以此类推,直到下标超界。实际上可以产生一个类似链表一样的序列。比如在这个例子中有两个下标的序列,0->2->3。

但如果有重复的话,这中间就会产生多对一的映射,比如数组2131,则映射关系为0->2, {1,3}->1, 2->3。这样,我们推演的序列就一定会有环路了,这里下标的序列是0->2->3->1->1->1->1->…,而环的起点就是重复的数。

我们先用快慢两个下标都从0开始,快下标每轮映射两次,慢下标每轮映射一次,直到两个下标再次相同。这时候保持慢下标位置不变,再用一个新的下标从0开始,这两个下标都继续每轮映射一次,当这两个下标相遇时,就是环的起点,也就是重复的数。

代码语言:javascript
复制
public int findDuplicate(int[] nums) {
        int slow = 0;
        int fast = 0;
        // 找到快慢指针相遇的地方
        do {
            //龟走一步
            slow = nums[slow];
            //兔走二步
            fast = nums[nums[fast]];
        } while (slow != fast);
        int find = 0;
        // 用一个新指针从头开始,直到和慢指针相遇
        while (find != slow) {
            slow = nums[slow];
            find = nums[find];
        }
        return find;
    }
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-07-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档