码迷,mamicode.com
首页 > 其他好文 > 详细

leetcode 287

时间:2018-10-06 16:35:51      阅读:135      评论:0      收藏:0      [点我收藏+]

标签:cycle   cpp   ber   duplicate   div   http   fast   不能   解答   

题目链接

这道题目要求在含有n+1个数字的数组中找出唯一一个出现多次的数字,而这些数字的范围是1-n,要求不改变数组本身以及常数空间。

首先我想到的办法是用Bitmap,即一个整型的数字X来表示某个数字是否出现过,如果出现过,那么就在X中对应的位置1。但是这个前提即使n不能太大了,否则整型的数字存储不下。反正这道题用了long long也不行。

这道题目看了别人的解答,可以说非常巧妙了。因为数组的范围是1-n,那么我们可以把数字之间的转移关系变成一个有向图。比如[2,1,2],那么2->2, 1->1,2->2。

这个例子太过简单,我们来举一个复杂一点的例子。此时数组为[3,1,3,4,2]。

首先第一个数字3指向下标3的数字4,

数字4指向下标4的数字2

数字2指向下标2的数字3

数字1指向下标1的数字1

这样变成一个有向图以后就是

技术分享图片

从这里看出来3,4,2形成了一个环,而环的入口点是3,这个问题就转换成了找图入口点的问题,可以把图看成链表,找链表入口点的问题就成了leetcode 142 了。利用快慢指针即可。

当然这里还有一个问题,看上图中,1是单独出来的,那么当我们初始化的时候,如果刚好碰到像1这种单独成环的怎么办?其实我们从数组第1个点进去即可,即下标为0的数字。因为题目说了数组中数字的范围是1-n的,所以0点处的值是不可能单独成环的,放心的从第一个数字开始找环即可。

 

class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int n = (int)nums.size();
        // if(n == 1) return 
        int slow = nums[0];
        int fast = nums[nums[0]];
        while(slow != fast){
            slow = nums[slow];
            fast = nums[nums[fast]];
        }
        fast = 0;
        while(slow != fast){
            slow = nums[slow];
            fast = nums[fast];
        }
        return slow;
    }
};

  

 

leetcode 287

标签:cycle   cpp   ber   duplicate   div   http   fast   不能   解答   

原文地址:https://www.cnblogs.com/leohujx/p/9747477.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!