找出数组中的缺失数据和重复数据

20130506微软实习生面试二面题目:

一个数组,大小为n,其元素大小范围为1-n。其中一些数缺失了,另外一些数则重复。先要求找出其中重复的数和缺失的数。



我几乎没怎么想,很快的写出:

/**************************
 * a[n],元素范围:1-n
 * 输出重复的和丢失的数
**************************/
void fa(int a[],int n)
{
    int *p  =   new int[n+1]();
    for(int i=0;i<n;i++)
    {
        p[a[i]]++;
    }
    set<int> m,r;///保存丢失和重复的数,也可以直接输出
    for(int i=1;i<=n;i++)
    {
        if(p[i]>1)
            r.insert(i);
        else if(p[i]==0)
            m.insert(i);
    }
    delete[] p;
}
面试官说,你的程度复杂度是多少?

我说时间复杂度是O(n),由于使用了辅助数组,空间复杂度也是O(n)。


“如果数组很大,需要的辅助空间太多,现在要求你优化,降低空间复杂度到O(1),怎么做?”

我想了几秒,不能辅助空间了,那时间上可能有损失。就说“那排序吧,排序后遍历一遍就行了。”

这时时间复杂度最好是O(nlogn),使用堆排序。(快速排序时间复杂度不是O(1),最好是O(logn),最坏是O(n))


面试官显然不满意。。。我自己都不满意,算法总不能牺牲时间。。。。

他说,现在要求时间O(n),空间O(1).


然后有想了会,说用位图的方法,他让我写出来,

然后我就把上面的数组改成位存储,悲剧的是好久没用bitset,一时想不起来bitset的定义的基本操作了。

就大致的写了下,并说明忘记bitset了,如果有手册我马上能写好。

面试官说那你不用stl,自己用内存吧。

想了下,平时都用一个int表示多个位,没有遇这种申请一块内存的情况,如果一次申请一大块内存该怎么进行位操作呢?

更不应该的是我把我的想法说出来了,他让我把一个int的位操作写出来,我写出来了,他说那多个int不是类似么?

我当时没想到要移动指针。。。和他多次纠结才说出来。。。

(以前项目经验太少,没做过,现场思考。。。就是不顺利。。。尤其是在面试那样紧张的氛围下)

最后他说,那你自己写个BitMap类吧,可以实现stl中bitset的操作,例如

BitMap bm(30);

bm[2] = 1;

bm[5] = 0;

这样的操作。

一开始写就觉得麻烦了。。。:vector什么的写过,重载下[]就行,返回元素的引用。这样才可以实现赋值。

可是bit引用,貌似又没遇到过??怎么办。。。。

我只好用函数的型式写了set()和reset()2个接口,虽然等价于上面的赋值,可是毕竟没满足他的要求。

然后他看了下,说“这就是你写的?”

我只好说重载操作符不太确定。。。。

然后他说:“作为一个工程师,写代码是很平常的事……”

我知道这次面试到此为止了。



回来后马上收拾东西,第二天要去sh实习了。

后来过了几天,问了好几个周围认识的人,都不会。

然后在网上,看到别人写的下面的算法:

void fun()
{
    int a[]={-1,3,3,3,3,3,3,8,9,8};///a[0]not use
    int n = sizeof(a)/sizeof(int)-1;

    for(int i=1;i<=n;i++)
    {
        while(a[a[i]]!=a[i])
        {
            int t = a[i];
            a[i] = a[t];
            a[t] = t;
        }
    }

    for(int i=1;i<=n;i++)
    {
        if(a[i]!=i)
        {
            cout<<i<<"\t";///丢失的数
            cout<<a[i]<<endl;///重复的数
        }
    }
}

好像是《编程珠玑》上的,这书我买了本英文版的,但是没看。。。。

唉,悲剧。



总结:之前面了好几家公司,基本都是一些常规算法,自己看到过的,基本很快的都答出来了。而且很少现场写代码的,基本是说出思路就行。然后就是问一些语言、OS、网络等知识点。一部分拿下了,得到offer,也有一部分悲剧了,几乎都是偏算法的。没见过的很少现场想出来。

微软的难度在于,随便你怎么说,说完我就让你写代码。一面的时候更悲剧。。。要写一个调度程序,我把数据结构写好后面试官说,很好,那你现在把你刚才说的用代码写出来。语言任意。


我室友面试的时候比我幸运多了,二面时算法是写冒泡排序!

当然一面和三面还有别的问题。他现在已经得到口头调剂offer了,去不去还没定。





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值