[经典面试题][谷歌]一个大小为n的数组,里面的数都属于范围[0, n-1],有不确定的重复元素,找到至少一个重复元素

题目

一个大小为n的数组,里面的数都属于范围[0, n-1],有不确定的重复元素,找到至少一个重复元素,要求O(1)空间和O(n)时间。

思路一

寻找重复元素,很容易想到建立哈希表来完成,遍历一遍数组就可以将每个元素映射到哈希表中。如果哈希表中已经存在这个元素则说明这就是个重复元素。这种方法可以很方便的在O(n)时间内完成对重复元素的查找。可是题目要求在O(1)的空间。因此采用哈希表这种解法肯定在空间复杂度上是不符合要求的。题目中数组中所以数字都在[0, n-1]区间范围内,因此哈希表的大小为n。因此我们实际要做的就是对n个范围为0到n-1的数进行哈希,而哈希表的大小刚好为n。对排序算法比较熟悉的同学不难发现这与一种经典的排序算法(基数排序)非常类似。而基数排序的时间空间复杂度刚好符合题目要求。因此尝试使用基数排序来解这道面试题。


代码

    /*---------------------------------------------
    *   日期:2015-02-19
    *   作者:SJF0115
    *   题目: 找重复元素
    *   来源:
    *   博客:
    -----------------------------------------------*/
    #include <iostream>
    #include <algorithm>
    using namespace std;

    class Solution {
    public:
        int IsReplication(int a[],int n){
            if(n <= 0){
                return -1;
            }//if
            for(int i = 0;i < n;){
                if(a[i] != i){
                    // 存在重复元素
                    if(a[i] == a[a[i]]){
                        return a[i];
                    }//if
                    swap(a[i],a[a[i]]);
                }//if
                else{
                    ++i;
                }//else
            }//for
            return -1;
        }
    };

    int main() {
        Solution solution;
        int num[] = {6,1,4,7,5,3,6,2};
        int result = solution.IsReplication(num,8);
        cout<<result<<endl;
    }

思路二

第一次遍历:对于每一个A[i] = A[i] * n
第二次遍历:对于每一个i,A[A[i]/n]++
第三次遍历:对于每一个i,A[i] % n就是出现次数
A[i]应该出现在A中的A[i]位置,乘以n、再除以n,很容易的来回变换;第二次遍历,对于A[i]本来所在的位置不断增1,但绝对不对超出n的,那每一个i出现的次数,就是A[i]对n取余。



代码

    /*---------------------------------------------
    *   日期:2015-02-20
    *   作者:SJF0115
    *   题目: 找重复元素
    *   来源:
    *   博客:
    -----------------------------------------------*/
    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;

    class Solution {
    public:
        vector<int> Replication(int a[],int n){
            vector<int> result;
            if(n <= 0){
                return result;
            }//if
            //第一次遍历
            for(int i = 0;i < n;++i){
                a[i] *= n;
            }//for
            // 第二次遍历
            for(int i = 0;i < n;++i){
                ++a[a[i]/n];
            }//for
            // 第三次遍历
            int count;
            for(int i = 0;i < n;++i){
                count = a[i] % n;
                if(count > 1){
                    result.push_back(i);
                }//if
            }//for
            return result;
        }
    };

    int main() {
        Solution solution;
        int num[] = {6,1,3,7,5,3,6,2};
        vector<int> result = solution.Replication(num,8);
        for(int i = 0;i < result.size();++i){
            cout<<result[i]<<endl;
        }//for
    }
时间: 2024-08-26 07:40:51

[经典面试题][谷歌]一个大小为n的数组,里面的数都属于范围[0, n-1],有不确定的重复元素,找到至少一个重复元素的相关文章

[经典面试题][去哪网]合并日期

题目 思路 声明一个大小为1001的数组array[1001],全部初始化为0 然后从前向后遍历数组,先处理[0,100,300]再处理[40,50,350].后面的价格覆盖前面的价格. 代码 /*------------------------------------- * 日期:2015-04-10 * 作者:SJF0115 * 题目: 合并日期 * 来源:去哪网 * 博客: ------------------------------------*/ #include <iostream>

[经典面试题]统计数组

[题目] 给定数组A,大小为n,数组元素为1到n的数字,不过有的数字出现了多次,有的数字没有出现.请给出算法和程序,统计哪些数字没有出现,哪些数字出现了多少次.能够在O(n)的时间复杂度,O(1)的空间复杂度要求下完成么? [分析] 我们知道原数组是没有排序的.如果排序了,很简单的.O(1)的空间含义,可以使用变量,但不能开辟数组或者map等来计数. 这个题目,很直接的解法就是两层遍历,O(n^2)的复杂度,O(1)的空间.空间满足了,但是时间没有. 很多类似的题目,都会用XOR的方法,大家仔细

数组大小为2n+1-数组相关算法java,找出需求的数据

问题描述 数组相关算法java,找出需求的数据 存在一个数组,数组大小为2n+2,里面有n对个数,例如:1,2,2,3,4,1.(数组是无序的,考虑排序的话一定会超过限制)这,6个数中的单独的数就是3,4,要你用你能想到的最高效率的方法找出来 解决方案 如果数组是连续的则可以用byte[] b = new byte[n+1];然后遍历一遍原数组,将遍历的值放入b的下标中计数,最后为1的那个下标表示数据是单独的. 这样的话总最多做3n+3次操作就能找全单独的数. 如果数组里面的数是无规律的,那么可

如何在azure网站中快速删除一个大文件夹

问题描述 如何在azure网站中快速删除一个大文件夹 我在Azure网站中部署了个我的website的应用,我现在想删去里面一个文件夹,大小大概有3G,我尝试使用ftp去做,但是速度太慢了,有们有什么快速的方法. 解决方案 Hi, 我们可以通过kudu这个工具快速的删除一个文件夹,我们首先去Azure网站的仪表盘下载发布配置文件,具体如下图: 打开配置文件找出用户名密码,然后我们打开IE输入https://***.scm.chinacloudsites.cn/, ***是你的网站名称,输入上面记

c++-对C++头文件改变如增加一个变量或者随便打sdflksdjf对整个项目都没反应是怎么回事儿

问题描述 对C++头文件改变如增加一个变量或者随便打sdflksdjf对整个项目都没反应是怎么回事儿 对C++头文件改变如增加一个变量或者随便打sdflksdjf对整个项目都没反应是怎么回事儿 解决方案 你是怎么随便打的, 一般头文件里都是声明的, 也可以定义函数(定义的话就直接是内联函数了),如果随便打的话估计都让你编译不过去吧 解决方案二: 项目中没有任何一个cpp文件#include这个头文件,所以随便打什么都不会有反应. 解决方案三: 我就随便打了:sdkfjlskdjfl(在任何地方)

怎样求一个固定4位随机数(字母+数字),且第一位不能为数字0,字母I和O不能在随机数中出现,不能连续两位都出现数字0.应该怎么做?

问题描述 怎样求一个固定4位随机数(字母+数字),且第一位不能为数字0,字母I和O不能在随机数中出现,不能连续两位都出现数字0.应该怎么做? 解决方案 解决方案二:首先构造一个字符串seed,排除了I.O等然后在字符串中随机取,取出来是0的话判断上一个是否也是0解决方案三:不好意思,我看得不是很明白!!是否能说详细点,或者贴段代码上来看看!!麻烦啦!!解决方案四:我一会给你个代码,很容易的.解决方案五:privatestringRandomStr4(){Randomr=newRandom();c

[经典面试题]输入一个排好序的数组的一个旋转,输出旋转数组的最小元素。

[题目] 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个排好序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3, 4, 5, 1, 2}为{1, 2, 3, 4, 5}的一个旋转,该数组的最小值为1. [分析] 这道题最直观的解法并不难.从头到尾遍历数组一次,就能找出最小的元素,时间复杂度显然是O(N).但这个思路没有利用输入数组的特性,我们应该能找到更好的解法.  我们注意到旋转之后的数组实际上可以划分为两个排序的子数组,而且前面的子数组的元素都大于或者等于后

PHP经典面试题集锦

 这篇文章主要介绍了PHP经典面试题集锦,搜集整理了常见的php面试题与相关的参考答案,供大家参考借鉴,需要的朋友可以参考下     本文较为详细的分析了PHP经典面试题.分享给大家供大家参考.具体如下: 做了一下网络上的php题目,不知不觉做到现在.....把答案贴出来,供参考之用. 1.用PHP打印出前一天的时间格式是2006-5-10 22:21:21(2分) ? 1 2 $a = date("Y-m-d H:i:s", strtotime("-1 day")

我的Java开发学习之旅------&amp;gt;Java经典面试题

摘自张孝祥itcast 从享受生活的角度上来说:"程序员并不是一种最好的职业,我认为两种人可以做程序员,第一,你不做程序员,你就没有什么工作可做,或者说是即使有可以做的工作但是你非常不愿意去做:第二,你非常痴迷和爱好程序,并且在这方面有一些天赋和优势.程序员的结局也是有两种:第一,默默退休,第二以程序员为起点或跳板,注意积累,跟对了好的老板或团队,找到和很好的搭档自己创业,成为IT金领和富翁." 人们在时间面前是平等的,吾生也有涯,所以,你的经验更丰富点,那不算什么,经验是用时间积累的