评论:**你个** LeetCode 287. 寻找重复数

99 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

一、题目描述:

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

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/fi…

二、思路分析:

开始看到这题以为蛮简单的,只要我把对应的数字,放到对应的位置,当有重复的时候就说明该数字就是重复的数字,时间复杂度O(n),空间复杂度O(1),可是后面一句把我整不会了,不能改变原数组,哦豁,这下可麻烦了。遇到困难睡大觉,我心中就剩下二分查找这种方法,时间复杂度应该为nlogn,空间复杂度为O(1),应该就是最优解了吧。

首先由于数中有重复值,假设我们随意去一个a,如果小于这个数的量严格大于我的a,那么重复的数就在小于a的那边查找,否则则是在大的那边查找。

写完美滋滋的看下搞笑评论区,哦豁第一条竟然不是抱怨的(还是有说这题脱裤子放屁的),我看到了一种O(n)时间复杂度,O(1)空间复杂度的题解循环链表解法,看完真的是妙啊!

快慢指针思想, fast 和 slow 是指针, nums[slow] 表示取指针对应的元素注意 nums 数组中的数字都是在 1 到 n 之间的(在数组中进行游走不会越界),因为有重复数字的出现, 所以这个游走必然是成环的, 环的入口就是重复的元素, 即按照寻找链表环入口的思路来做。

三、AC 代码:

代码一:

/**
 * @param {number[]} nums
 * @return {number}
 */
var findDuplicate = function(nums) {
    let left=1,right=nums.length-1;
    while(left<=right){
        let mid=Math.floor((left+right)/2);
        let cnt=0;
        for(let i=0;i<nums.length;i++){
            if(nums[i]<=mid){
                cnt++;
            }
        }
        if(cnt>mid){
            right=mid-1;
        }else{
            left=mid+1;
        }
    }
    return left;
};

代码二:

/**
 * @param {number[]} nums
 * @return {number}
 */
var findDuplicate = function(nums) {
    let fast=0,slow=0;
    while(true){
        fast=nums[nums[fast]];
        slow=nums[slow];
        if(slow===fast){
            fast=0;
            while(nums[slow]!==nums[fast]){
                fast=nums[fast];
                slow=nums[slow];
            }
            return nums[slow];
        }
    }
};

四、总结:

题目做完还是多看下评论区,不仅搞笑解压,还可以收获很多不同的思想。