一道百度面試題題解

來源:互聯網
上載者:User
  問: A廠有1萬個工人,編號0-9999,( EE[10000] ), 1個廠長( GG )指派任務, 1個監工( MM )管理工人.廠子忙的時間不確定,可能突然很忙,1天接到任務5000多個,1個任務只能分配給1個工人做, 也可能好幾十天沒新任務.廠長分配任務給這1萬個工人幹,按工人編號一個一個來,到最後一個工人就又從頭開始,任務完成時間各不相同,可能一個工人在分配任務的時候手裡還有任務, 就得換下一個。

  但是這1萬個工人都很懶,領到了任務先不做,需要監工1個1個去問,如果工人有任務,就做,如果工人沒任務,則不做。廠長只管分任務,1個1個來,可能幾天也沒新任務,不累; 但是監工很累,監工每天都要看所有工人的情況,即使這些工人都沒有任務, 實際上每天工人(80%左右)是沒任務的,請問,怎麼讓監工的工作輕鬆下來. 比如說每天只問1小半工人.

  Peak Wong:

  分析如下:

  因為“任務完成時間各不相同” ,所以有可能a,b,c某天都有任務,但b的任務最先完成,那麼當b的任務完成後,有任務的人的工號可能是不連續的;

  用一個數組表示1萬個工人是否有任務,並儲存最後被分配任務的人的工號;

  1)從前一天“最後被分配任務的人的工號”開始,依次問下一個工號的人,置對應的工作狀態,直到碰到前一天無工作,且當天也無工作的人; 並更新當步最後有工作的人的工號為當天的“最後被分配任務的人的工號”;

  2)從前一天“最後被分配任務的人的工號”開始,依次問上一個工號且前一天有工作的人;

  問題是監工可以知道那些資訊,否則還不是一個一個接著去問。
  還有就是tailzhou的步驟1消耗的時間T1, 工人完成的時間T2,如果T2

  所以很多條件都沒有限制。

  可是仔細想想,就是監工要記錄所有工人的工作狀態,然後每天只查詢在工作的工人就可以了。(並且記錄誰還在工作中)

  其實最根本的解決之道是在每次廠長分配任務時,監工也被通知誰被分配了任務。而現在題目的假設是廠長太忙了,來不及通知監工(其實讓監工分配就行了)。

  解決這個問題很簡單,監工只要記錄(也可能是他猜測)上次廠長分配任務最後分配到那個人就可以了。

  然後每天查詢時,除了監督前一天來在工作的人外,還要查看從上次分配到任務的編號的下一個編號開始的工人,向後依次查詢,知道遇到一個沒有被分配工作的人(這個工人後面不會再有人被分配任務了).同時監工還要記錄或猜測哪個工人是當天最後被分配任務的。在“查看從上次分配到任務的編號的下一個編號開始的工人,向後依次查詢”過程中,如果工人的話可信,詢問他們就可以了。如果不可信,那麼可以猜測為最後一個昨天空閑,今天忙的工人就可以了。

  其實,監工既然可以監督,他總得有渠道知道當天那個工人還有活要做(不然所有工人都可以說今天我沒有任務呀),所以沒有這麼複雜的問題。

  解決問題:

  有一問:監工是不是問了以後,工人就會一直把工作做完?

  如果這樣的話,最簡單的一個考慮,他第一次問的時候記住這個工人今天能否做完,不能做完的話,哪天才能做完。

  監工實際上只需要在工人做完了以後的第二天去問就可以了。因為不做完,廠長不會給他分新任務。

  但問題說:但是監工很累,監工每天都要看所有工人的情況,即使這些工人都沒有任務那又不一樣了,就是說監工必須每天問,不然工人不會開始工作。

  這時候就是沒有工作的工人不需要問。

  首先工作隊列,每個人問一遍,今天能做完的移到空閑隊列。

  空閑隊列,二分尋找,找到非閒置,往前處理完,今天能做完的不動,不能做完的移到工作隊列。

  很簡單的問題阿。二分尋找需要問的人非常少的。

  絕對能滿足樓主說的:比如說每天只問1小半工人,用我的方法廠長分任務的時候不需要通知監工。

  實際上通知也沒有意義,因為是按順序分配,監工實際上需要知道的是今天有多少新任務。

  就算不知道,用二分尋找10000人也最多需要10幾次。

  這10幾次,再根據實際上每天工人(80%左右)是沒任務的,所以實際上每天問的人只有20%左右。

  1.問題分析

  現在的情況是監工每天要查看所有的工人,催他們工作,因為不催他們不開工,即要訪問EE[10000]的每個元素一次。目標是每天只問一小半的工人,實際上沒有工作的工人是不需要問的,最理想的情況就是監工只問有工作的工人,或者儘可能少地問沒有工作的工人,即要儘可能少地訪問EE[10000]的元素。

  怎麼辦呢?監工想了一個辦法,他做了一萬張卡片,每張卡片上寫著工人的編號,從0-9999,恰好和數組EE[10000]的下標對應。

  監工拿著他的秘密武器上陣了,0號,有工作沒?沒有。好,放右邊口袋。1號,有工作沒?有。今天能幹完嗎?能。好,放右邊口袋(並且放在0號後面)。2 號,有工作沒?有,今天能幹完嗎?不能。嗯,放左邊。3號,沒有。放右邊(1號後面)。4號,今天幹不完,放左邊。……第二天,先看右邊(昨天沒事的), 0號,有工作沒,有,今天能幹完嗎,能,好,不動。1號有工作沒,有,幹不完,好,放左邊(接著昨天后面放)。3號,沒有,哦,廠長GG還沒有分配到這裡阿,那明天檢查空的從這裡開始就可以了(記住),但今天仍然輕鬆不了,因為可能是從後面的號碼過來,並且分配到前面來了。右邊全部查完了。再查左邊。2 號,今天能幹完,放右邊(並且放在0號後面)。阿,又碰到了1號了,今天的檢查結束。第三天,總算可以輕鬆了。從3號開始,先查右邊。今天做得完,不動,做不完,移到左邊後面,碰到沒有任務的,或者碰到3號,右邊檢查完。再看左邊,做得完的,移到右邊,並且按順序插入其它卡片中間,做不完的,不動,直到碰到今天新加入的做不完的,或者整個左邊的卡片都檢查完。

  說了這麼多,實際上就是左邊的是工作的隊列,右邊的是沒工作的隊列,左邊和右邊的區別就是右邊的要保持按編號排序(因為廠長GG分配任務是按順序分的)。再拿支鉛筆,在有的卡片上做做記號。工作輕鬆不少。以上都是假設工人必須每天催才會工作,並且監工每天都是在廠長分配任務之後才去催。如果工人催一次就會一直工作,那麼簡單,監工只需要在卡片上記下還要幾天才去問就行了。如果監工是每天早上去催,廠長去可能在清早(問之前)或下午(問之後,但工人還沒工作完)去分任務。

  如果是前者,當然沒問題,如果是後者問題來了,因為3號是今天才能完工的,但也是放在右邊,如果廠長剛好分了2號和4號,那麼按上面的邏輯,4號就催不到了。

  所以為了避免這種情況,當天能完的還不能放在空閑裡。嗯,只要再準備一個口袋就行了。好在監工的衣服上面有兩個口袋,下面也有兩個,用了下面兩個,上面還有兩個沒有被使用。拿一個來用就行了。

  檢查下面的左右口袋時,凡是當天能做完的,都放在左上。OK,先右下,再左下,當天能做完的這會兒放右上,再把左上的按順序插入右下。應該沒問題了吧,不管廠長何時分任務,監工只需要看自己的口袋就可以了。右下需要訪問的是從昨天訪問的沒工作的開始,再到一個新的沒工作的。左下都要訪問。右上或左上的卡片只需要整理。因為實際上每天工人(80%左右)是沒任務的,都在右下,並且也可能好幾十天沒新任務,這下輕鬆了,只用問小部分工人就能保證工作正常進行了。

  好了,如果想先類比一遍怎麼辦,用大腦類比,10000人太多想不過來,累。寫個程式吧。要寫程式得先有演算法。

  2.演算法

  以下演算法類比最一般的情況,即監工不知道廠長何時分任務,廠長在一天的任何時候都可以分任務,工人每天都要問才工作,監工只在早上去催(為了簡化工時的計算,即工時以天為單位)。

  完全的隨機起點類比,即此方法可從任何監工想要採用此方法的時間點開始。

  假設一個任務完成的時間是1-N天,廠子一天接到的新任務數是0-M個。用T分鐘類比一天。定時器是精度毫秒級。

  A.用0-N之間的數初始化EE[10000],類比當前工人的工作狀態。EE[i]表示工人還要多少天完成這個任務。EE[i]=0,表示沒任務。

  B.設定定時器,廠長分任務定時器為1-T*60*1000毫秒之間某個時間,監工定時器設為T*60*1000毫秒。

  C.廠長定時器到,廠長分任務。用c記錄廠長從哪裡開始。第一次時有個隨機初始化的工程,隨機一個0-9999之間的數,然後找到第一個EE[i]=0的i,從這個c=i開始分配。

  隨機產生0-M,如果=0,則c=i不變,如果是1-M之間的值,則一個個查,碰到EE[i]=0的,給他隨機一個1-N的值,直到分完這些任務,並且c=最後分到的+1。這個題目是研究監工的問題是,廠長比較輕鬆,下次讓他繼續從這裡找下去。

  重新設定廠長定時器,定時為T*60*1000-上次定的時,再加上1-T*60*1000毫秒之間某個時間,因為廠長也只會一天分一次,所以先要把今天的時間用完,再加上下一天的某個時間,(從前面可以看出,廠長的定時器設成T也是一樣的,只要考慮一下訪問共用資料的問題,這裡先不考慮這個問題)。

  D.監工定時器到,監工問工人。

  建立四個鏈表。a(今天還不能做完的),b(沒有工作的),c(今天可以做完的),d(今天可以做完的),初始化為空白。但b為有序鏈表。c和d輪流使用。

  第一次定時到,訪問EE[10000],今天不能做完的(EE[i]> 1)接到a的尾巴上,能做完的(EE[i]=1)接到c的尾巴上,沒有工作的(EE[i]=0)接b,d空。

  第二次定時到,訪問b,今天不能做完的接到a的尾巴上,能做完的接到d的尾巴上,並且記錄出現有工作的人後再出現沒有工作的人的結點指標p。如果沒有這樣的人,那就是鏈表第一個人或者為空白(大家都有工作)。但不管怎樣必須把整個鏈表b訪問一遍。

  訪問a,不能做完的不動,能做完的接到d的尾巴上,最後將c中的元素插入b。注意,鏈表中元素唯一,也就是說移到另一個鏈表的時候,也意味著從原鏈表刪除。

  第三次定時到,從p開始訪問b中的元素,今天不能做完的接到a的尾巴上,能做完的接到c的尾巴上,直到找到一個沒有工作的或者已經全部找了一遍(找 的時候調整p到新的位置)。到鏈表最後一個後,可能要從頭找。

  訪問a,不能做完的不動,能做完的接到c的尾巴上,最後將d中的元素插入b。

  第四次定時到,和第3次類似,只是c和d的位置對調了一下。到這時,監工的工作已經輕鬆了,整個系統將按這個新的方式一直運行下去。

  監工的定時器不需要重新設定。

  a,b,c,d中的元素內容為工人編號,訪問時文法類似if(EE[p-> index]> 1)。
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.