最近在跟身邊的同學進行秋招分享的時候,發現很多同學在面試的時候都被問到了乙個玻璃球會不會被摔碎的問題,有些讓簡單講一下思路,有的則是要現場寫一下實現的**,下面就簡單介紹乙個這個題目。
問題是這樣的,現在在我們面前有一棟高為n的大樓,我們手中有m個玻璃球,現在我們想知道從最高從哪一層把玻璃球扔下,玻璃球會不碎,問在最壞的情況下,我們至少要試多少次,才能得出結果,還有乙個補充條件就是在0層算地面,肯定不會碎,一層開始有高度,從這層開始可能會碎。
舉個簡單的小例子,大家可能就明白了。
假如,n=0,m=1;
此時在地面上,不用測試,直接返回。
假如n=100, m=1;
由於只有乙個玻璃球,此時只能從一層開始一層一層實驗,因此最壞的情況是我們一直試到第100層,依沒碎,此時我們的試驗次數是100次。
假如n=3,m=2;
我們先從第二層開始試,如果碎掉,我們測試第一層,如果沒碎,我們測試第三層,當然也可以用乙個玻璃球從第一層開始一層一層的測試,但是這種情況,我們獲取結果最壞的情況下需要測試3次,不滿足題目中至少的要求。
下面就展開分析一下:
第一種情況,n=0,直接返回0,不用測試,我們就知道玻璃球不會碎;
第二種情況,m=1,直接返回n,此時我們只有乙個玻璃球,只能一層一層測試,最壞的情況是到n層也不碎;
第三種就是常規情況,我們有多於乙隻的玻璃球,它會在樓層中間某層碎掉,我們假設從第 i 層丟下乙個玻璃球,此時可能會發生兩種情況,第一種,碎了,那我們要用 m-1 只玻璃球去在第1~i 之間的樓層繼續測試,第二種情況沒碎,那麼我們要用m只玻璃球在第 i+1 到n之間的樓層去測試。
通過上面的分析,我們可以知道,我們最終得出的結果跟樓層數與玻璃球數都有關係,假設結果用f(n,m)表示,那麼:
在第一種情況下,可以表示為,f(0,m)=0;
第二種情況下,f(n,1)=n;
第三種情況的第一種小情況為:1+f(i-1,m-1);
第三種情況的第二種小情況為:1+f(n-i,m);
分析到這裡我們就知道,除去特殊情況,我們所需要的結果就是在第三種情況中,哪個是次數最多的(最壞情況),哪個就是我們從第 i 層拋下第一顆玻璃球所需要的結果,我們要做的就是,將 i 從1到n遍歷,每次遍歷都會獲取乙個值,我們在這n個值中取最小值,就是我們最終要的結果。
寫到這裡可能有些同學會有疑問,又是最多,又是最少,這到底是怎麼回事,其實,我們這麼考慮,題目要求是最壞的情況下,我們最壞需要多少次測試出結果,這個最壞,就是對應著從某一層拋下,需要最多的次數,而我們最初要從哪一層拋下才能保證次數最少,這個初始值還不確定,因此我們要做的就是將樓層從第一層到最頂層遍歷一遍,找出第一次拋玻璃球從哪層開始,需要的次數最少,這裡面其實包含有這兩個邏輯,最壞是比較兩個值哪個大,至少是比較n個值哪個小。
分析到這裡,相信大多數同學都已經知道,這道題目該怎麼做了,下面就附上**:
public int solution(int n, int m) else
} public int process(int n, int m)
if (m == 1)
int min = integer.max_value;
for (int i = 1; i <= n; i++)
min = math.min(min, math.max(process(i - 1, m - 1), process(n - i, m)));
} return min + 1;
}
寫到這裡,我們的基本分其實已經得到了,思路沒問題,也能得到我們想要的結果了,但是還有沒有更好的方法呢,我們再回過頭分析一下有沒有優化的方法,利用我們上面的**,假如我們在第10層丟下玻璃球,碎了,那麼我們接下來是要實驗第1~9層的,需要計算一遍1到9層的資料,接下來我們從第11層丟下玻璃球,也碎了,這時候我們要計算第1到10層的資料,此時,第1到9層就屬於重複計算了。
我們仔細分析會發現,採用這種暴力遞迴的方式,會多重複計算很多次資料,因此我們採用動態規劃的方式,用乙個陣列去存下每層的資料,這樣當再次需要這些資料的時候,就可以直接去取用,不用再次重複計算。
附上優化後**:
public int solution(int n, int m)
if (m == 1)
int dp = new int[n + 1][m + 1];
for (int i = 1; i <= n; i++)
/**最外層迴圈是樓層的遍歷
裡面的迴圈是不同玻璃球個數下獲取的最小值作為二維陣列在該下標下的值
*/for (int i = 1; i <= n; i++)
dp[i][j] = min + 1;
}} return dp[n][m];
}
經過優化,我們將演算法時間複雜度從o(n!)降低到o(m*n^2); 外企面試官最喜歡問的問題
1.請介紹一下你自己。這是外企常問的問題。一般人回答這個問題過於平常,只說姓名 年齡 愛好 工作經驗,這些在簡歷上都有,其實,外企最希望知道的是求職者能否勝任工作,包括 最強的技能 最深入研究的知識領域 個性中最積極的部分 做過的最成功的事,主要的成就等,這些都可以和學習無關,也可以和學習有關,但要...
面試官最常問的問題總結(一)
ps 作為面試官或應聘者,都應該了解了解的問題,不知道能不能稱之為 面試模式 1 請你自我介紹一下你自己?2 你覺得你個性上最大的優點是什麼?3 說說你最大的缺點?4 你對加班的看法?回答樣本 如果是工作需要我會義不容辭加班,我現在單身,沒有任何家庭負擔,可以全身心的投入工作。但同時,我也會提高工作...
面試官常問的集合框架問題(一)
有關集合框架問題 一 list 集合 1 迭代器的remove方法與集合的remove的區別?只需要了解迭代器在記憶體的執行 指標 迭代器與集合是兩個物件,如果說在迭代器中呼叫集合中的remove方法,會報currentmodifyexception錯誤。2 array與arraylist的有何區別...