其他
逻辑面试题:1+1=2最复杂的打开方式
The following article is from 小K算法 Author 小K算法
作者 | 小K
出品 | 公众号:小K算法 (ID:xiaok365)01故事起源一个逻辑学教授,有三个学生,而且三个学生都非常聪明! 有一天教授给他们出了一个题:
教授在每个人脑门上贴了一张纸条
每个人的纸条上都写了一个正整数,且某两个数的和等于第三个数
每个人可以看见另两个数,但看不见自己的
02场景重现要破解这个问题,就要先扮演这个角色,我们来场景模拟一下,3个同学围绕站成一个圈。
每个人自己的数只能是另两数之和或者之差,所以每个人都有2种可能。
每个人都无法确认自己到底是哪一个,也不能从其他人那里得到更多信息。
03寻找突破口要排除不可能的解,必须要从边界入手,如果没有任何条件限制,那这就是一个无解的问题。
再回到问题描述,“每个人的纸条上都写了一个正整数”,这就是最关键的信息,它暗示了很多其它信息。如果有一个人计算出来的数不是正整数,那这一种情况就被排除。
这个数不可能是负数,因为2个不相等的数,一定是用大的减去小的,那剩下的非正整数就只能是0,也就是有2个数相等的情况。
假设小K看到的是这样的场景,那一定能猜到自己的数就是10。
04从小规模分析关注小K很久的同学应该已经发现了,小K最喜欢用的手段,就是从小规模开始分析问题,再逐层推进。
如果2个数相等,抽象一下,不就是一个最简单的1+1=2的问题吗?
05第1人猜不出第1轮询问,如果第1人猜不出,对于后面的人来说给出了另一个信息,就是这3个数肯定不是(2,1,1),因为如果是(2,1,1)那第1人肯定就猜出来了啊。
如果小A看到的场景刚好是这样,(2,y,1),那y不是1,肯定就是3了呀。
06第2人猜不出如果第2人猜不出,对于第3人来说,也给出了很多信息,说明一定不是(2,1,1),(1,2,1),(2,3,1)。
07第2轮如果第1轮第3人也没猜出,就会进入下一轮。
第2轮第1人能猜出的情况如下:
正确的解有5个:(3,1,4),(1,3,4),(2,7,9),(4,5,9),(3,5,8)。
对应的另外两个数分别是:(108,36),(36,108),(32,112),(64,80),(54,90)。
08任意情况比如为(98,27,71)的情况,根据上面的规律,最终还是会回归到1+1=2的问题。
3个数要先约掉公约数,等比例的情况都是相同的
任意情况,都会在有限轮次之后被某个人猜出来
最先猜出来的人,一定是数字最大的人
所有逻辑推理的根基都是1+1=2 每多一轮,解的个数以斐波那契数列递增
09代码实现
int x, y, z, level;
};
Node f[10000];
int last1, last2, tail;
void init() {
f[0] = Node{2, 1, 1, 1};
f[1] = Node{1, 2, 1, 2};
f[2] = Node{2, 3, 1, 2};
f[3] = Node{1, 1, 2, 3};
f[4] = Node{2, 1, 3, 3};
f[5] = Node{1, 2, 3, 3};
f[6] = Node{2, 3, 5, 3};
last1 = 3;
last2 = 1;
tail = 7;
}
void solve(int round, int person, int x) {
int n = (round - 2) * 3 + person, total;
for (int i = 0; i < n; ++i) {
total = tail;
for (int j = last2; j < total; ++j) {
if (i % 3 == 0) {
f[tail++] = Node{f[j].y + f[j].z, f[j].y, f[j].z, 4 + i};
} else if (i % 3 == 1) {
f[tail++] = Node{f[j].x, f[j].x + f[j].z, f[j].z, 4 + i};
} else {
f[tail++] = Node{f[j].x, f[j].y, f[j].x + f[j].y, 4 + i};
}
}
last2 = last1;
last1 = total;
}
for (int i = last1; i < tail; ++i) {
int temp = 0;
switch (person) {
case 1:
temp = f[i].x;
break;
case 2:
temp = f[i].y;
break;
case 3:
temp = f[i].z;
break;
}
if (x % temp == 0) {
int s = x / f[i].z;
printf("(%d, %d, %d), level=%d\n", f[i].x * s, f[i].y * s, f[i].z * s, f[i].level);
}
}
}
init();
solve(2, 3, 144);
return 0;
}
(36, 108, 144), level=6
(32, 112, 144), level=6
(64, 80, 144), level=6
(54, 90, 144), level=6
10总结第一眼看上去觉得简单,初步思考发现没有思路,感觉有难度,认真一步一步的分析下去,又会发现其实还是很简单,关键在于能否发现本质规律。这是一道极强的逻辑推理,大家一定要认真分析领悟,相信你可以学到很多的知识,打开思维模式。
2、我的阿里二面,为什么MySQL选择Repeatable Read作为默认隔离级别?
点分享
点点赞
点在看