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

Find the Duplicate Number 287

时间:2015-11-19 18:25:48      阅读:161      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:https://leetcode.com/problems/find-the-duplicate-number/

题目描述:

一个数组包含n+1个数字, 这n+1个数字是1-n之间的数字,并且只有一个数字出现重复(不一定只出现2次,可能重复多次),要求不能改变数组的数字,找出重复的数字

 

分析:

n+1个数字包含1-n之间的数字,肯定会出现重复,如果重复的数字只出现两次,那么问题比较容易解决,只要用n+1个数字的和减去1-n个数字的和,得到的就是重复出现的数字。

但是本题中说明了出现的数字不一定出现2次,排序的方法可以再nlog(n)时间内解决,但是题目要求不能改变数组。

 

实际上如果可以改变数组可以用桶排序的方法在O(n)方法内解决。

或者可以用额外的内存可以用一个n+1标记数字出现的次数在O(n)方法内解决。

 

设置一个下标,每次下标变动为当前下标处值。如果这么不断变换的话这条转换链上除了第一个节点之外,其他节点都表示出现过一个数字(这个下标是上一个下标处的的数组值)。

假如这条转化链上存在环并且环的起点不是第一个节点的话,环的起点就是出现重复的数字。

至于怎么保证环的起点不是第一个数字,我们可以用0这个下标作为起点,应为所有的数字都是1-n所以转换链上不可能在出现0。

 

#include <map>
#include <vector>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <stack>
#include <iostream>

using namespace std;

int findDuplicate(vector<int>& nums) {
    int len = nums.size();
    if (1 == len) return nums[0];

    int low = 0, fast = 0;
    do {
        low = nums[low];
        fast = nums[fast];
        fast = nums[fast];
    } while(fast != low);

    low = 0;
    while(low != fast) low = nums[low], fast = nums[fast];

    return low;
}

int main()
{
    vector<int> nums;
    int n;
    //freopen("in.dat", "r", stdin);
    while(scanf("%d", &n) == 1) {
        nums.push_back(n);
    };
    cout<<findDuplicate(nums)<<endl;
    return 0;
}

 

Find the Duplicate Number 287

标签:

原文地址:http://www.cnblogs.com/li-xingtao/p/4978268.html

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