找出數組中的缺失數據和重複數據

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了,去不去還沒定。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章