力扣:287. 寻找重复数

力扣:287. 寻找重复数,第1张

题目链接:287. 寻找重复数
题目:

给定一个包含 n + 1 个整数的数组 nums ,其数字都在 [1, n] 范围内(包括 1 和 n),可知至少存在一个重复的整数。
假设 nums 只有 一个重复的整数 ,返回 这个重复的数 。
你设计的解决方案必须 不修改 数组 nums 且只用常量级 O(1) 的额外空间。

示例 1:

输入:nums = [1,3,4,2,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 数组建图,每个位置 i 连一条 i→nums[i] 的边。由于存在的重复的数字 target,因此 target 这个位置一定有起码两条指向它的边,因此整张图一定存在环,且我们要找到的 target 就是这个环的入口,那么整个问题就等价于 142. 环形链表 II。
定义快慢指针,在一个循环中,慢指针走一步,快指针就走两步,这个循环的结束条件是找到重复元素,即快慢指针的值相等。但是上面的循环容易忽略一种情况:指针到不了位置0,因为范围为[1, n],所以无论快慢指针如何走都不能到达位置0。这时将慢指针置于位置0,再循环一遍,直到再次找到重复元素。因为两个循环后快慢指针的值都相等,所以返回快慢指针中的任何一个值都可以。
代码(c++):

//范围:[1, n]
//只能有一个重复的整数,并且重复整数一定存在
//重复的那个数字可以重复多次(两次以上包括两次)

//快慢指针
class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int slow = 0, fast = 0;
        //找到重复元素,但指针到不了位置0,因为范围为[1, n]
        do {
            slow = nums[slow];  //慢指针走一步
            fast = nums[nums[fast]];    //快指针走两步
        } while (slow != fast);
        //将慢指针置为0,解决上面位置到不了0的问题
        slow = 0;
        while (slow != fast) {
            slow = nums[slow];
            fast = nums[fast];
        }
        //当快慢指针的值相等时,即找到了重复元素
        //return fast;  //返回slow或fast均可
        return slow;
    }
};
  • 时间复杂度:O(n);
  • 空间复杂度:O(1)。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/921548.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-16
下一篇 2022-05-16

发表评论

登录后才能评论

评论列表(0条)

保存