1000个瓶子里面999瓶是水,多少次试验确定哪瓶是毒药
題圖 | @望川鳥
本文來自寒食君的投稿,公眾號:字節流
在文章之前我先拋出一個有趣的問題,相信有的同學是看過的,沒有看過的也不打緊兒,文章下面會進行解答。問題如下:
現在有1000個瓶子,里面999瓶是水,1瓶是毒藥。最少通過多少次的試驗,能確定哪瓶是毒藥。
這個問題你可以思考一下,我先來說一說最近在生活中遇到的另一間相關的事。
前段時間在設計一張數據表的時候遇到了一個小問題。情況是這樣的,一條數據有著三種狀態,這三種狀態是可能疊加并且重復的。什么意思呢?我舉一個通俗的例子來類比一下。
孔子曰:吾日三省吾身。高乎?帥乎?富乎?高、富、帥可以說是一個人的三種狀態。比如通過「骨骼生長」這個函數的處理,人可以擁有「高」這個狀態;通過「自我打理、運動健身」這個函數的處理,人可以擁有「帥」這個狀態;通過「發奮圖強」這個函數的處理,人可以擁有「富」這個狀態。什么是疊加?就是一個人可以擁有其中的多種狀態;什么是重復?比如一個人多次「奮發圖強」,依然會擁有「富」的狀態。
解釋完這些,再回到問題本身。我當時想的是,給每個狀態一個單獨的布爾類型(可以判斷真或假)的字段,然后在進行處理時對相應狀態進行分別判斷。這樣雖然也能完成任務,但是顯得笨重且不優雅。舉兩個顯而易見的例子:
假如這條數據將來不止三種狀態,難道需要重新對數據庫進行改造嗎?而且程序也要相應地修改。數據庫作為基礎設施,一旦確定,修改地成本是很高的。
因為一條數據可能會經過多次相同類型地處理,假如這樣設計,每次處理前程序都需要知道當前狀態是真是假,處理完再決定是否修改狀態碼。這會導致程序的冗余、不簡潔。
...
針對這些問題,X叔(組里一位我很敬重的老哥)建議我可以用一個籠統的字段 status,然后每種狀態的值可以設置為1、2、4...這樣。我心想,妙啊。
多重狀態疊加產生的值是不會產生重復的,比如「高富」=3,「高帥」=5,「富帥」=6等等。而且以后有新的狀態,假設新增「健康」這些,到時候,直接約定為相應值8、16等等。
那這和位運算有什么關系呢?我們來看下面這張圖。
而在重復處理方面,位與運算帶來了更加簡潔的操作。舉個例子,假如當前狀態時是「高帥」,需要再次進行「帥」處理,如果按照傳統的加減方式,需要判斷當前有沒有「帥」這個狀態4,有的話不加,沒有的話加上4。這無疑是非常繁瑣的。
使用位與運算,會簡潔很多,比如:
很方便。在進行位或的時候也是如此,可以結合具體情況試一試。
除此之外,在一些編程語言的源碼里,經常會用到位運算,因為它不僅高效,而且有時候更靈活。比如JDK8里在優化HashMap的擴容時,將取模運算換成了位運算。可以參考上篇滴滴好用,但是不安全。HashMap:我也是。
解決了這個問題。回頭看看文章開頭的智力題。
可以先公布一下答案:10。
假設現在有十只小白鼠,如何10只小白鼠的生死來找出那一瓶毒藥呢?我們先將1000個瓶子用二進制編號,就像下圖:
從000000001-1111111111,代表1號到1024號(1001-1024個瓶子可以忽視,因為只需要1000個),可以看到,每個數都有十位,那么我們讓每只小白鼠負責一列,將這一列的編號出現1的瓶子中的液體混合著喝下去。如果某只小白鼠死了那么可以判定這列為1的所有瓶子中,有一瓶是毒藥。通過十只小白鼠的生死情況組合來看,不難發現那瓶是毒藥的瓶子編號。
如果你覺得數量太大,有些納悶,可以減少數量,假設總共共有八個瓶子,其中一瓶是毒藥。仔通過這種方式來計算一下。
總結
以上是生活随笔為你收集整理的1000个瓶子里面999瓶是水,多少次试验确定哪瓶是毒药的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数学建模安装matlab,数学建模神器—
- 下一篇: php explain type等级,m