1.原题
2.转述
- 有64瓶新冠疫苗
- 现在其中有一瓶不小心混入了有毒物资
- 该混入有毒物质的疫苗,小白鼠喝了之后30分钟会死亡(不用考虑剂量)
- 那么现在只剩下30分钟了
- 问最少使用多少只小白鼠可以100%找到有毒的那瓶
- (不用考虑疫苗损坏,只要喝一丁点有毒的,小白鼠30分钟就会死)
- 提示:可以使用二进制编码
解答
- 1.将64瓶新冠疫苗从0~63进行编号
- 2.将每一瓶疫苗根据编号转为二进制
package cn.hanjiaxiaozhi.interview;
/**
* Author hanjiaxiaozhi
* Date 2020/7/23 16:58
* Desc
*/
public class BinaryTest {
public static void main(String[] args) {
for (int i = 0; i <= 63; i++) {
//将i转为二进制字符串格式
String binaryString = Integer.toBinaryString(i);
System.out.println(i + " : " + binaryString);
}
}
}
/*
00 : 000000
01 : 000001
02 : 000010
03 : 000011
04 : 000100
05 : 000101
06 : 000110
07 : 000111
08 : 001000
09 : 001001
10 : 001010
11 : 001011
12 : 001100
13 : 001101
14 : 001110
15 : 001111
16 : 010000
17 : 010001
18 : 010010
19 : 010011
20 : 010100
21 : 010101
22 : 010110
23 : 010111
24 : 011000
25 : 011001
26 : 011010
27 : 011011
28 : 011100
29 : 011101
30 : 011110
31 : 011111
32 : 100000
33 : 100001
34 : 100010
35 : 100011
36 : 100100
37 : 100101
38 : 100110
39 : 100111
40 : 101000
41 : 101001
42 : 101010
43 : 101011
44 : 101100
45 : 101101
46 : 101110
47 : 101111
48 : 110000
49 : 110001
50 : 110010
51 : 110011
52 : 110100
53 : 110101
54 : 110110
55 : 110111
56 : 111000
57 : 111001
58 : 111010
59 : 111011
60 : 111100
61 : 111101
62 : 111110
63 : 111111
-------------
******
*/
-
3.拿出6只小白鼠和上面的6个二进制位对齐
-
4.让这6只小白鼠去喝对应的二进制位是1的疫苗
-
如:
- 右边第1个小白鼠喝最右边二进制位为1的疫苗,也就是奇数编号的疫苗
- 左边第1个小白鼠喝最左边二进制位为1的疫苗,也就是32~63编号的疫苗
- 其他类似…
- 5.30分钟后观察有哪些小白鼠死了
-
如:
- 小白鼠都没有死,那么0号疫苗有毒
- 小白鼠都死了,那么63号疫苗有毒
- 如果左起124号小白鼠死了说明 52号 : 110100疫苗有毒
-
如果还不理解可以逆向思考:
- 假设43 : 101011号疫苗有毒,那么左起1 3 5 6号小白鼠死亡
- 那么如果观察到1 3 5 6号小白鼠死亡也能反推出43 : 101011号疫苗有毒
- 那么1000瓶疫苗,其中1瓶有毒,最少需要xx只小白鼠?
- 2^10=1024 > 1000 也就是10位二进制可以最0~999瓶进行编号,所以需要10只
-
如果要写代码需要涉及到二进制位的操作
- 取二进制位用&符合
- 如: 1100010
- 我们要依次取出每一个二进制位是什么?
- 如取右起第3位二进制位
- 1100010 >>> 3
- 11000 &
- 00001
- 0
- 说明原来的右起第3位二进制位为0