Hulu面試題


1、給定一個N位數,例如12345,從里面去掉k個數字,得到一個N-k位的數,例如去掉2,4,得到135,去掉1,5,得到234。設計算法,求出所有得到的N-k位數里面最小的那一個?

解決方案一:
(1)第一步要確定剩余N-K位的數的最高位:
從個位開始算起,從第N-K位開始向高位比較,求出最小數字,作為高位。
例如,3 1 1 2 3 3 1,K=3時,從7-3=4開始(為2),向上比較發現,1更小,所以高位設置為1,記錄此時位置P1(等於也可以替換,從而取最高位的1).
(2)再確定次高位:
從N-K-1開始向上到P1-1,此時最小數字為1.
依此類推,最后就可以得到最小數1121.

解決方案二:
例如,1 2 3 4 5 6 7, K=3
剩余N-K位,則定義一個N-K的數組R,用來存放所選數字。
(1)初始化R,存最低N-K位 4567
(2)向上遇到1,則3<R最高位4:
此時需要對R進行調整,調整規則如下,如果高位數字小於相鄰低位數字,則用高位數字替換之。
最高位再用當前數字替換。
於是,得到3456.
不斷執行以上過程,就得到了最終結果1234.
對方案一中舉例進行驗證,正確。

解決方案三:

求每位數字元素,依據元素建立最小堆進行處理,若頭為0,設為次高位,以此類推。。。時間復雜度O(nlog(n))。。

2、“找明星”,N個人中,只有一個明星:明星不認識其他所有的人,而其他人都認識明星,這些人中也可能相互認識。你每次只可以問一個人是否認識另一個人這樣的問題,問最少問多少次可以找出明星。

分析:該問題在創新工場(Innovation Works)和葫蘆(Hulu)的面試中都被問到:
N個人中只有一個明星:明星不認識其他所有的人,而其他人都認識明星,不是明星的人可能認識也可能不認識。你每次只可以問一個人是否認識另一個人這樣的問題,問最少問多少次可以找出明星。

方法:從N個人中找兩個人a b,問a是否認識b,若a認識b則a肯定不是明星排除a,若a不認識b則分兩種情況討論,為明星為1,不為明星為0。
1: 0 0
2: 0 1(不可能,a肯定認識b)
3: 1 0
4: 1 1(不可能,只有一個明星)
只有1,3兩種情況,這兩種情況中b肯定不是明星。因此問一個問題我們便可以排除掉一個人,最多經過n-1次便可以找到明星。

擴展:
如果有兩個明星呢?所有的人都認識明星,明星之間互不認識,其它的人可能認識也可能不認識。最少問多少次可以找出明星?
一種顯然的方法是:先通過第一種方法找出一個明星,然后在剩下的n-1個人種找出第2個明星。這樣總共需要問(n-1 + n - 2)=2n-3次問題。

這個問題等價於找未知序列數中的最小數
我們將reg這個函數等價為以下過程:
如果i認識j,記作i大於等於j,同樣j不一定大於等於i,滿足要求
i不認識j記作i<j
對明星k,他不認識所有人,則k是其中最小的數,且滿足其余的人都認識他,也就是其余的人都大於等於k.
這樣問題就被轉換了。

就拿N=5來說
首先有數組S[5]={A,B,C,D,E}這5個變量,里邊存放着隨機數,求是否存在唯一最小數,如果存在位置在S中的哪里。(樓主這里是這個意思,按我的理解題中這個最小數一定是存在且唯一的)

int finds(S,N)
{
    int flag=0;//用於判定是否有明星,即當前最小數另外出現幾次
    int temp=0;//存放最小數在S中的位置
    for(i=1;i<N;i++)
   {
      if(!reg(S[i],S[temp])//如果temp標號的數小於i標號的數
     {
         temp=i;
         flag=0;//更換懷疑對象(最小數)時,標記清零
      }
      elseif(reg(S[temp],S[i])//如果temp里存放的確實是唯一最小數是不會跑進這里來的
      {
           flag++;
`     }
    }
    if(flag>0) return -1;//表示沒有明星,例如所有的數都相等
    return temp;//返回明星在S中的位置
}

遍歷 1~n 這n個人;
首先取出 1號 和 2號, 如果 1 認識 2, 那么把 1 去掉;--如果1不認識2,就可以把2去掉了。
如果 2 認識 1, 那么把 2 去掉;
如果 1 和 2 都互相不認識,把他們都去掉;
如果有剩下,在拿剩下的和3號進行比較;
如果沒有剩下的,則拿出3號和4號進行比較;

如此循環;
最后若剩下最后1個人,再遍歷一遍看是否剩下的n-1個人都認識它

時間復雜度分析:
每對之間的比較最多比較2次, 每對之間的比較至少淘汰1個人,要淘汰n-1個人最多比較 2*(n-1)次;
所以時間復雜度是 O(n)的。。

3、兩個有序鏈表的合並。看過這個題,考慮下邊界問題,可以用O(n)時間,O(1)空間解決。寫完后,說我代碼有個小bug,然后討論后改之。問這個算法在哪種條件下不work,想了許久,突然靈光一現,想出可能鏈表有環或者兩個鏈表有可能有公共節點。他很開心,說很久沒有人能同時想出兩個case了。

node merge_sorted_list(const node head1,const node head2)
{
    if((NULL == head1) && (NULL == head1))
    {
        return NULL;
    }
    else if(NULL == head1)
    {
        return head2;
    }
    else if(NULL == head2)
    {
        return head1;
    }
    else
    {    
        node head = NULL,p1 = NULL,p2 = NULL;


        if(head1->value >= head2->value)
        {
            head = head1;
            p1 = head1->next;
            
            p2 = head2;
        }
        else
        {        
            head = head2;
            p2 = head2->next;
            
            p1 = head1;
        }

        node p = head;

        while((NULL != p1) && (NULL != p2))
        {
            if(p1->value >= p2->value)
            {
            
                p->next = p1;


                p = p1;


                p1 = p1->next;
            }
            else
            {
                
                p->next = p2;


                p = p2;


                p2 = p2->next;
            }
        }
        
        p->next = p1 ? p1 : p2;
        //if(NULL != p1->next)
        //    p->next = p1;
        //else
        //    p->next = p2;
        return head;        
    }
}

遞歸實現:

Node * MergeRecursive(Node *head1 , Node *head2)
{
    if ( head1 == NULL )
        return head2 ;

    if ( head2 == NULL)
        return head1 ;

    Node *head = NULL ;

    if ( head1->value > head2->value )
    {
        head = head1 ;
        head->next = MergeRecursive(head1->next,head2);
    }
    else
    {
        head = head2 ;
        head->next = MergeRecursive(head1,head2->next);
    }

    return head ;
}
//不帶頭節點的鏈表
#include <stdio.h>
#include <malloc.h>

struct Node
{
    int value;
    struct Node *next;
};

typedef struct Node * node;

node CreateList(int iStart,int num)
{
    node head = NULL,p = NULL,q = NULL;
    
    for(int i = num;i > 0 ;i --)
    {
        p = (node)malloc(sizeof(struct Node));
        p->value = iStart + i;


        if(head == NULL)
        {
            head = p;
        }
        else
        {
            q->next = p;
        }
        q = p;        
    }

    p->next = NULL;

    return head;
}

node merge_sorted_list(node head1,node head2)
{
    if((NULL == head1) && (NULL == head2))
    {
        return NULL;
    }
    else if(NULL == head1)
    {
        return head2;
    }
    else if(NULL == head2)
    {
        return head1;
    }
    else
    {
        node p = NULL,p1 = NULL,p2 = NULL;

        if(head1->value >= head2->value)
        {
            p = head1;
            p1 = head1->next;
            
            p2 = head2;
        }
        else
        {        
            p = head2;
            p2 = head2->next;
            
            p1 = head1;
        }

        while((NULL != p1) && (NULL != p2))
        {
            if(p1->value >= p2->value)
            {          
                p->next = p1;

                p = p1;

                p1 = p1->next;
            }
            else
            {          
                p->next = p2;

                p = p2;

                p2 = p2->next;
            }
        }    
        p->next = p1 ? p1 : p2;

        return head1->value >= head2->value ? head1 : head2;
    }
}

void display(node head)
{
    node p = head;

    while(NULL != p)
    {
        printf("%3d",p->value);

        p = p->next;
    }
    printf("\n");
}

int main()
{
    node head1 = NULL ,head2 = NULL,head = NULL;

    head1 = CreateList(5,6);
    head2 = CreateList(5,6);

    display(head1);
    display(head2);

    head = merge_sorted_list(head1,head2);
    display(head);


    return 0;

}

2、字符串A和字符串B。是否B包含了A所有的字符串,要考慮字符的個數問題,比如A:aabb , B: abccc,就不滿足條件了。這個題目跟google當年的筆試題很像,開一個256的int[]數組做hashtable,很容易解決了。由於之前沒有考慮上述的情況,他指出來了,稍微改下,就過了

 

3、一個n*n迷宮,方塊里可能是牆,可能是路,問怎么走出出口,求最短路徑。先說思路,然后寫偽代碼。很簡單的寬度優先,每個方格里記錄走的步數和來自於哪個方塊。很快就解決了。

分析:寬度有限搜索問題,采用隊列結構。。

 

1)N個數,選出任意兩個數求和,問所有這些可能性的和是多少。我說最簡單的方法是模擬,O(N^2),然后問有沒有更簡單的,想了想,計算了下所有數出現的個數是 (N-1)/2,所以很簡單,就是 sum*(N-1)/2,時間復雜度是O(N)

 

2)問試卷最后一個題。之前聽同學說過,我自己想過。A B兩個有序數組,A中選一個,B中選一個,要求和為某個指定值m,問怎么選。感覺是《編程之美》上一維數組中求兩個數和的變形,所以只要變換一下:A中的數從頭往尾走,B中數從尾往前走就好;但是這么會遺漏,如果沒找到,用相同的方式,A中的數從尾往頭走,B中的數從頭往尾走,看能否找到

 

3)問知道怎么確定有環鏈表。說知道。然后問,怎么確定環的起點節點。然后說沒見過。他說,浙大的很奇怪,第一個問題都會,而第二個問題都不會。然后我開始想,最簡單的用hash表保存已遍歷的節點。然后他說需要常數空間。想了很久大概15分鍾不會,讓他提示下。說如果兩個鏈表有公共節點,問怎么去找這個公共節點,想了幾分鍾,想出來了。只要都遍歷一下得到長度的信息,利用這個信息再遍歷一次,就可以找到公共節點。然后想到第有環的只是一個變種,只要把環斷開。就成了第一個問題。然后叫我寫代碼,很順利的寫完。

 

4)已知兩個矩形的四個節點信息,然后給一個API——可以得到某個點在是否在某矩形內,問怎么判斷矩形相交。答曰,矩形相交不需要這么復雜,只要判斷線段相交就行。可能他之前沒想到我會這么回答,仔細解釋了下,他說可行。然后問有沒有特殊情況,我說有,一個矩形在另一個矩形內,可能線段不相交,矩形也相交了。然后答曰,這個只要判斷小矩陣的幾點是否在大矩陣內就可以了

 

5)問一個n*n的方塊內,有一條環形路徑。路徑上的點都是1,其他點都是0.。給路徑中的任意一個點,問這個路徑所包含的面積。想了一分鍾,覺得粉兩步走:1)深度優先找路徑 2)寬度優先算面積 然后解釋了下,說可行

 

更多詳見:http://tianwei.sinaapp.com/2012/09/%E9%9D%A2%E8%AF%95%E9%A2%98%E6%94%B6%E9%9B%86/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM