[百度面試題]100層樓,球可能會在某一層樓摔壞,問用2個球,最壞情況下幾次測試可以找出該樓層
該題還可以擴充套件,比如說給更多的球,如3個球,多少次測試可以找出樓層。
分析如下:
用動態規劃解這個問題
設f(a, b)為a個球做b次測試可以測試到的樓層數,可以確定的樓層數即為f(a, b) + 1,因為第1層不需測試,需要測試的樓層號僅僅為[2, f(a, b) + 1]共f(a, b)層,也就是a個球b次測試可以測試到的樓層數。考慮第1次測試,測試的樓層記為x:
1)如果球破了,就需要測試x下面的樓層,還剩下a-1個球b-1次測試,測試的樓層數為f(a - 1, b - 1)。
2)如果球沒有破,那麼需要測試x上面的樓層,還剩下a個球b-1次測試,測試的樓層數為f(a, b - 1)。
a個球b次測試為1)2)測試的樓層數及第1次測試了的1層,所以:
f(a, b) = f(a - 1, b - 1) + f(a, b - 1) + 1 (1)
考慮初始條件,顯然f(a, 1) = 1(a >= 1,1次測試可以測試到的樓層數當然為1,不論多少個球),f(1, b) = b(b >= 1,1個球做了b次測試當然測試到了b層樓)。
強調一下:注意f(a, b)為測試到的樓層數,f(a, b)加上不需測試的樓層才是可以確定的樓層(f(a, b) + 1)。
動態規劃解(1)式即可。
一般來說,a >= 2(1個球意義不大),可以計算出f(2, 64) = 2080,f(3, 64) = 43744,f(4, 64) = 679120。
程式如下
- /*
- * a balls, n floors, want to find the minimum number of floor
- * where a ball drops will be broken. output the minimum number
- * of drops
- * METHOD: dynamic programming
- * assum the answer is b, that is the number of drops
- * f(a, b): the maximum number of floors, when a balls and b drops
- * f(a, b) = 1 + f(a, b - 1) + f(a - 1, b - 1)
- * obviously, f(a, 1) = 1; f(1, b) = b
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <assert.h>
- #include <string.h>
- #define DEBUG
- #define MAX_B 64
- #define MAX_A 16
- #define f(a, b) ff[a - 1][b - 1]
- static unsigned int a, n;
- static unsigned longlong ff[MAX_A][MAX_B];
- staticvoid init()
- {
- int i;
- memset(ff, 0, sizeof(ff));
- /*f(a, 1) = 1*/
- for (i = 1; i <= MAX_A; i++){
- f(i, 1) = 1;
- }
- /*f(1, b) = b + 1*/
- for (i = 1; i <= MAX_B; i++){
- f(1, i) = i;
- }
- }
- static unsigned longlong do_find_min_drops(int i, int j)
- {
- if (f(i, j))
- return f(i, j);
- f(i, j) = do_find_min_drops(i - 1, j - 1) +
- do_find_min_drops(i, j - 1) + 1;
- return f(i, j);
- }
- staticvoid do_print_drops(int i, int j, unsigned longlong min,
- unsigned longlong max)
- {
- if (min > max)
- return;
- if (1 == i){
- assert(j == max - min + 1);
- for (i = min; i <= max; i++){
- printf("%5d", i);
- }
- printf("/n");
- printf("*************/n");
- return;
- }
- if (1 == j){
- assert(min == max);
- printf("%5lld/n", max);
- printf("*************/n");
- return;
- }
- printf("%5lld", min + f(i - 1, j - 1));
- do_print_drops(i - 1, j - 1, min, min + f(i - 1, j - 1) - 1);
- do_print_drops(i, j - 1, min + f(i - 1, j - 1) + 1, max);
- }
- staticvoid print_drops(int ans)
- {
- do_print_drops(a, ans, 2, n);/*[2..n]*/
- }
- staticvoid find_min_drops()
- {
- /*NOTE: number of floors are [1, n]*/
- int i, j, m;
- int ans;
- #if 0//def DEBUG
- for (i = 2; i <= MAX_A; i++){
- for (j = 2; j <= MAX_B; j++){
- printf("f(%d, %d) = %lld/n", i, j, do_find_min_drops(i, j));
- }
- printf("****************/n");
- }
- #endif
- i = 1;
- j = MAX_B;
- while (i <= j){
- m = (i + j) / 2;
- if (do_find_min_drops(a, m) + 1 < n)
- /*
- * why +1? because the 1st floor need not to test
- */
- i = m + 1;
- else
- j = m - 1;
- }
- ans = i;
- if (ans > MAX_B){
- printf("the number of the maximum drops(MAX_B = %d) is too small/n", MAX_B);
- printf("maximum floors "
- "can be tested is f(%d, %d) + 1 = %lld + 1. STOP/n", a, MAX_B, f(a, MAX_B));
- exit(0);
- }
- printf("the minimum drops: %d/n", ans);
- print_drops(ans);
- #ifdef DEBUG
- for (i = 1; i <= a; i++){
- for (j = 1; j <= ans; j++){
- printf("f(%d, %d) = %lld/n", i, j, f(i, j));
- }
- printf("****************/n");
- }
- #endif
- }
- int main(int argc, char **argv)
- {
- if (3 != argc){
- fprintf(stderr, "usage: %s a n/n", argv[0]);
- exit(-1);
- }
- a = atoi(argv[1]);
- n = atoi(argv[2]);
- printf("a = %d/tn = %d/n", a, n);
- assert(a > 0 && a < MAX_A && n > 0);
- init();
- find_min_drops(); /*drops: 1*/
- return 0;
- }
這裡,我採用遞迴的方法打出了測試過程,解釋如下:
1)2個球,100層樓時,可以計算出
f(2, 13) = 91
f(2, 14) = 105
因此需要的測試次數為14,測試過程為
15 2 3 4 5 6 7 8 9 10 11 12 13 14
*************
28 16 17 18 19 20 21 22 23 24 25 26 27
*************
40 29 30 31 32 33 34 35 36 37 38 39
*************
51 41 42 43 44 45 46 47 48 49 50
*************
61 52 53 54 55 56 57 58 59 60
*************
70 62 63 64 65 66 67 68 69
*************
78 71 72 73 74 75 76 77
*************
85 79 80 81 82 83 84
*************
91 86 87 88 89 90
*************
96 92 93 94 95
*************
100 97 98 99
*************
第1次測試為15層,如果球破了,則剩下的一個球測試[2, 14],總共的測試次數最多為1+13=14 如果球沒破,則測試28層,如果破了,剩下的一個球測試[16, 27],總共的測試次數最多為1+1+12 = 14 ... 如果球沒破,測試100層,如果破了,剩下的一個球測試[97, 99],總共的測試次數最多為1{11} + 3 = 14 如果球沒破,則不存在樓層使得球可以摔破。 2)3個球,100層樓,可以計算出 f(3, 8) = 92 f(3, 9) = 129 因此測試測試最多為9次。測試過程: 38 9 2 3 4 5 6 7 8 第1個球測試38層,如果破了,第2個球測試9層,如果還破了,剩下的一個球測試[2, 8]層,總共的測試次數2 + 7 = 9 ************* 16 10 11 12 13 14 15 如果第2個球沒破,則測試16層,如果破了,第3個球測試[10, 15],總共的測試測試3 + 6 = 9 ************* 22 17 18 19 20 21 如果第2個球沒破,則測試22層,如果破了,第3個球測試[17, 21],總共的測試測試4 + 5 = 9 ************* 27 23 24 25 26 如果第2個球沒破,則測試27層,如果破了,第3個球測試[23, 26],總共的測試測試5 + 4 = 9 ************* 31 28 29 30 如果第2個球沒破,則測試31層,如果破了,第3個球測試[28, 30],總共的測試測試6 + 3 = 9 ************* 34 32 33 ************* 36 35 ************* 37 ************* 67 45 39 40 41 42 43 44 如果第1個球沒破,則測試67層,如果破了,第2個球測試45層,如果破了,第3個球測試[39, 44],總共的測試次數3 + 6 = 9。以下類似,不再重複。 ************* 51 46 47 48 49 50 ************* 56 52 53 54 55 ************* 60 57 58 59 ************* 63 61 62 ************* 65 64 ************* 66 ************* 89 73 68 69 70 71 72 ************* 78 74 75 76 77 ************* 82 79 80 81 ************* 85 83 84 ************* 87 86 ************* 88 ************* 105 94 90 91 92 93 ************* 98 95 96 97 ************* 101 99 100 ************* 103 102 ************* 104 ************* 3)對於更多球的情況,輸出的測試方法分析起來有些麻煩,但是上面的動態規劃法求出的結果就容易理解了,且是保證正確的。相關推薦
[百度面試題]100層樓,球可能會在某一層樓摔壞,問用2個球,最壞情況下幾次測試可以找出該樓層
該題還可以擴充套件,比如說給更多的球,如3個球,多少次測試可以找出樓層。 分析如下: 用動態規劃解這個問題 設f(a, b)為a個球做b次測試可以測試到的樓層數,可以確定的樓層數即為f(a, b) + 1,因為第1層不需測試,需要測試的樓層號僅僅為[2, f(a, b) +
[百度面試題]100層樓丟玻璃球問題
轉自 : http://blog.csdn.net/prstaxy/article/details/8655988 有一棟100層高的大樓,給你兩個完全相同的玻璃球。假設從某一層開始,丟下玻璃球會摔碎。那麼怎麼利用手中的兩個球,用什麼最優策略知道這個臨界的層是第幾層??
百度面試題(2018.10.29) 內容生態事業部
介紹自己的專案 專案的資料量有多大 zookeeper在follower死掉後,如何重新選舉? hdfs的資料儲存和讀取過程? hdfs在資料儲存過程中,如何保證副本的資料一致性? 當時我沒想起來,於是被問道,如果是你設計,你會如何實現hdf
百度面試題:找出陣列中出現次數超過一半的數
現在有一個數組,已知一個數出現的次數超過了一半,請用O(n)的複雜度的演算法找出這個數。 Thinking……/>/> Thinking……/>/>/> Thinking……/>/>/> Thinking……/>/>/> Think
隨機數——百度面試題
題目如下: 已知一隨機發生器,產生0的概率是p,產生1的概率是1-p,現在要你構造一個發生器,使得它構造0和1的概率均為1/2;構造一個發生器,使得它構造1、2、3的概率均為1/3;...,構造一個發生器,使得它構造1、2、3、...n的概率均為1/n,要求複雜度最低。
js百度面試題
小編推薦:Fundebug專注於JavaScript、微信小程式、微信小遊戲,Node.js和Java實時BUG監控。真的是一個很好用的bug監控費服務,眾多大佬公司都在使用。 說出以下程式碼執行結果 var a = {n: 1} var b = a; a.x = a
百度面試題 字串中單詞的逆轉,即將單詞出現的順序進行逆轉
#include<stdio.h> #include<string.h> void Rotate(char *start,char *end) { if(start == NULL || end == NULL) return ; while(sta
百度面試題之二叉樹層次遍歷(從上到下,從下到上)
1.二叉樹的層次遍歷 遞迴解法 class Node(object): def __init__(self, v, left=None, right=None): self.value = v self.left = l
陣列中只出現一次的兩個數字(百度面試題)
題目要求: 在一個數組中,其餘數字都是成堆出現的,只有兩個數字出現了一次。儘快找到這兩個數字。 思路: 之前有過類似題,是一組陣列中只有一個數字出現了一次,其餘數字都是成對出現的。找到這個數字。這道題
百度面試題:自己實現strlen,考慮32位,64位機器,考慮效能
沒辦法, 現在的大公司面試就面這個, 你不得不研究下底層的實現.要點:1) 字長邊界對齊以便加快速度. 對齊時也要考慮機器的位數哦. 2) 一次測試4個(或者8個)位元組中是否含零的技巧. 3) 需要自適應32bit/64bit機器. 定義magic變數是要使用lo
【校招】百度面試題-4種陣列去重的方法
第一部分原文連結:http://blog.csdn.net/u011277123/article/details/54091442第二部分原文連結:http://blog.csdn.net/icessunt/article/details/69098474方法一: findI
百度面試題:一個單鏈表,長度未知,如何快速的找出位於中間的那個元素
問題: 一個單鏈表,長度未知,如何快速的找出位於中間的那個元素? 設定兩個指標,p1,p2, 開始p1,p2均位於連結的頭部。 p1 每次步進兩步, p2 每次步進一步 當p1到達連結串列的末尾時,p2所在的位置就是連結串列的中間元素 時間複雜度為O(n) 詳
百度面試題——簡單運算
問題:要求不使用+ - * / < >運算子號判定給定兩個非零數的大小。輸入:多組輸入兩個數a和b。輸出:輸出min=較小的數字,max=較大的數字實現程式碼:#include <stdio.h>int main(int argc,char* argv
百度面試題之 啟動執行緒方式有哪幾種,執行緒池有哪幾種
1、啟動執行緒方式: 要啟動的可以分為兩類:返回結果和不返回結果。對於這兩種,也分別有兩種啟動執行緒的方式: 1)繼承Thread類,implements Runnable介面 2)實現Callable介面通過FutureTask包裝器來建立Thread執行緒、使用Ex
百度面試題--度度熊想去商場買一頂帽子,商場裡有N頂帽子,有些帽子的價格可能相同,度度熊想買一頂價格第三便宜的帽子,問第三便宜的帽子價格是多少?
第一種方法:可以使用LIst 進行每次加入時進行判斷是否包含,將重複的資料不再加入List中 最後再找出List中第三便宜的帽子,若list的size小於3輸出-1; 特點:每次加入資料
二叉樹系列——二叉樹的最大距離(即相距最遠的兩個葉子節點,程式設計之美,百度面試題)
來自於程式設計之美3.8。 題目:如果我們把二叉樹看做圖,父子節點之間的連線看成是雙向的,我們姑且定義“距離”為兩個節點之間邊的個數。寫一個程式求一棵二叉樹中相距最遠的兩個節點之間的距離。 如下圖所
百度面試題——摸黑白球
上網查資料的時候偶然間看到一道百度的面試題,題意大概如下: 一個桶,100個黑球100個白球,每次取走兩個球,如果同色則放入一個黑球,如果異色則放入一個白球。求最後只剩下一個黑球的概率。 思考過程: 一、首先排除了計算機模擬的思路,因為最後答案要求的概率,計算機模擬出的都是
從一道百度面試題到分析輸入url到頁面返回的過程(或者查詢返回過程)
輸入地址瀏覽器查詢域名的 IP 地址 這一步包括 DNS 具體的查詢過程,包括:瀏覽器快取->系統快取->路由器快取...瀏覽器向 web 伺服器傳送一個 HTTP 請求伺服器的永久重定向響應(從 http://example.com 到 http://www
百度面試題 求字串中不含重複字元的最長子串長度
#include<iostream> #include<string> using namespace std; void MaxNoRepeatStrLength(string a) { unsigned int hashtable[128] =
面試題:1000瓶水其中有一瓶水有毒,有10只老鼠並且只要老鼠喝了有毒的水必死。請問怎樣通過一次實驗找出有毒的那瓶水。
import java.util.Arrays; import java.lang.StringBuilder; import java.util.Scanner; public class toxicWater { public static final int waterNumber = 1000;