【每日一题】LeetCode. 287. 寻找重复数

每日一题,防止痴呆 = =

一、题目大意

给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。
在这里插入图片描述
在这里插入图片描述
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-the-duplicate-number

二、题目思路以及AC代码

这道题刚看到的时候以为是用异或做了 = =,结果发现题目中说重复数的重复次数可能大于1次,这用异或就没有办法了,主要还是参照题解学习了三种解题方式。

思路一:二分

题目要求时间复杂度小于O(n2),所以无非就是O(nlogn)和O(n),一看到O(nlogn),我首先是想到快排,然后稀里糊涂就给过了(其实题目要求不能修改原数组的),所以就可以考虑二分。

但是对于二分,我们需要构造单调序列,这里可以考虑单调序列cnt,其中cnt[i]表示在nums数组中,小于等于i的数的个数,我们用target表示我们要找的重复数,那么可以想象当i < target的时候,cnt[i] 是小于等于i的(当且仅当重复数没有占用小于target数的位置时等号成立),当i >= target的时候,cnt[i]是大于i的,所以我们就可以根据以上情况进行二分,即如果cnt[mid] <= mid,那么target一定在右侧的数组中,如果cnt[mid] > mid,那么target一定在左侧的数组中或者就是mid.

按道理来说,应该先计算cnt数组,复杂度是O(n),然后再二分,复杂度是O(logn),总体复杂度O(n),但是由于题目要求不能使用额外的存储空间,所以这里就得现算cnt,造成结果的复杂度是O(nlogn).

思路二:二进制

和思路一差不多,这里的思路是考虑确定重复数的各个二进制位。即我们考虑重复数的第i位是否是1,我们令x表示nums数组中,第i位为1的总个数,y表示1~n中,第i位为1的总个数。那么如果x > y,那该位就是1,如果x <= y,那么该位就是0.

我们可以分情况考虑上述的问题。重复数我们分为重复1次,和重复多次。如果是重复一次,那么当重复数第i位为1的时候,则x = y + 1,当重复数为0的时候,则x = y,满足上述提到的条件。然后当重复数是重复多次的时候,必定要替代一个原来的数B,如果重复数第i位为1,B第i位为0,那么x > y+1,如果重复数第i位为1,B第i位为1,那么x = y+1 > y,如果重复数第i位为0,B第i位为1,那么x < y,如果重复数第i位为0,B第i位为0,那么x = y,综上所述,都满足上述提到的判定重复数第i位值得条件,即如果x > y,那该位就是1,如果x <= y,那么该位就是0.

思路三:判环

该题同样可以建立成一个图中判环的问题。我们令i -> nums[i]为边建图,那么由于有重复数的原因,所以势必有两个顶点同时指向同一个顶点,此时有环出现,而环的起点就是我们要找的重复数。

可以使用快慢指针来实现。

AC代码

上述代码我实现了一下思路一和思路三,列在下面。

思路一:

class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int n_size = nums.size();
        int l = 1, r = n_size - 1;
        int mid = (l + r) >> 1;

        while (l < r) {
            mid = (l + r) >> 1;

            int x = 0;
            for (int i=0;i<n_size;i++) {
                if (nums[i] <= mid) {
                    x++;
                }
            }

            if (x <= mid) l = mid + 1;
            else r = mid;
        }

        return l;
    }
};

思路三:

class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int slow = 0, fast = 0;
        do {
            slow = nums[slow];
            fast = nums[nums[fast]];
        } while(slow != fast);

        slow = 0;
        while (slow != fast) {
            slow = nums[slow];
            fast = nums[fast];
        }

        return slow;
    }
};

如果有问题,欢迎大家指正!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 这个错误信息意味着你正在尝试运行一个叫做“leetcode.toggleleetcodecn”的命令,但是系统找不到这个命令。 这可能是因为你使用的软件或工具不支持这个命令,或者这个命令在你当前的上下文中不可用。你可以检查一下你的命令拼写是否正确,或者查看相关的文档和说明来了解如何正确地使用这个命令。 ### 回答2: 当我们在使用LeetCode插件时,可能会遇到错误提示“command 'leetcode.toggleleetcodecn' not found”。这个问题出现的原因是插件没有正确安装或者没有激活。下面是解决这个问题的几个步骤: 1. 确认插件是否安装成功 首先,我们需要确认LeetCode插件是否已经成功安装。可以通过在VS Code的侧边栏中找到“Extensions”图标,然后在搜索框中输入“LeetCode”来查找插件是否存在。如果插件存在,那么就说明安装成功。 2. 确认插件是否已经激活 在安装插件之后,我们还需要激活LeetCode插件才能使用它提供的功能。可以在VS Code的侧边栏中找到“Extensions”图标,然后点击“Installed”选项卡,在LeetCode插件下方看到是否显示“Activate”按钮,如果是,则需要点击该按钮进行激活。 3. 检查配置项是否正确设置 在安装插件并激活之后,LeetCode插件的配置项需要正确设置才能顺利使用。可以在VS Code的右下角找到“Settings”按钮,然后搜索“LeetCode”来找到插件的配置项。在配置页面中可以看到“Language Switch”选项,此处需要确保开启了中文支持。 如果以上三个步骤都已经确认完成,但还是遇到了“command 'leetcode.toggleleetcodecn' not found”这个错误,则可以尝试卸载并新安装插件,或者尝试咨询LeetCode官方支持团队。 ### 回答3: 这个错误提示是因为在使用LeetCode的插件时,该插件没有被正确加载或安装。在使用该插件之前,需要确保已经按照LeetCode插件的安装步骤正确地安装和配置了插件。 为了解决该问题,可以采取以下步骤: 1. 检查是否已经安装了VS Code和LeetCode插件。如果没有安装,需要按照官方文档的指导进行安装。 2. 确认已经登录了LeetCode账号。在登录成功之后,需要在LeetCode插件的设置中填写正确的账号信息。 3. 检查是否在VS Code的用户设置中配置了相关的设置项。在VS Code的用户设置中,需要添加以下配置项: ```json "leetcode.endpoint": "https://leetcode-cn.com/graphql", "leetcode.defaultLanguage": "javascript", "leetcode.workspaceFolder": "${workspaceFolder}/leetcode", "leetcode.skeletonFileExtension": "js" ``` 4. 如果 LeetCode 插件的版本不是最新版本,则需要更新插件。在VS Code中,可以通过侧边栏中的扩展选项或者运行命令“Extensions: Check for Extension Updates”来升级插件。 5. 如果以上步骤都无效,可以尝试新安装LeetCode插件,并按照官方文档的指导进行配置和使用。 总之,要解决'leetcode.toggleleetcodecn' not found 错误,需要仔细检查和核对安装、配置、登录等这些步骤,以确保LeetCode插件能够正常工作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值