1.0 5个人去一个海岛寻宝,最后一共找到了100枚金币。他们约定了一个分配方案,如下:五个海盗按照抽签的顺序依次提出方案,某一个人提出方案之后,剩余存活的人投票表决:方案需要获得超过半数人的认可之后才能被通过,否则方案提出者将会被扔进大海喂鲨鱼,某一个方案被通过后游戏就结束。注:每个人的投票都是在追求自己利益的最大化:保证自己不会被喂鲨鱼的前提下,尽量使自己分到更多的金币。
题目的意思应该很清楚了,五个人依次按照抽签顺序给出自己的分配方案,如果某个方案没有获得通过,那么该方案的提出者就会被扔进大海喂鲨鱼;如果方案通过了,游戏就结束了。问题是:你认为第几个提出方案的存活概率最大,以及ta要如何提出方案才能最大概率存活,并且尽量是自己获得多的金币呢?存活的那个人最多可以获得多少金币?
在往下看之前,不防先停下来想一想:如果你遇到了这道题,你的会怎样思考呢?
提出方案的人要想存活下去就必须让自己的方案被大多数人接受,也就是ta必须要争取某些票或者放弃一些票。那么方案提出者如何做出决策呢?ta应该争取哪些人的票?或是又该放弃哪些人的票呢?到这里可以停下来想一想哦。
方案提出者要想争取到某个人的票就必须知道在ta的方案提出之前那个人能分到的最大金币数量,在不损害那个人利益的前提下才能争取到某个人的投票。也就是方案提出者要尽量去获取其他人在自己提出方案之前可能获得的金币数量,然后尽可能去争取一些人的投票、以及放弃一些人的票。那么如何得知其他人的最大的利益呢?
如果方案提出者不能获取到这个信息的话,这题基本无解了。因为方案提出者不能确定ta提出的方案能被哪些人接受,也就是生死存活全靠掷骰子了.....
如果从前往后推测其他人可能的最大利益,会陷入死循环:第一个人做决定前得知道第2,3,4,5个人的决定,从前往后是无法推出任何答案的,所以可以考虑尝试从后往前推测其余人可能的最大利益。在得知其余人的最大利益之后,就能得知自己的方案能够得到哪些人的支持,问题也就迎刃而解了。到这里可以先停下来,尝试从后往前给出你的推测和答案哦~
01 从后往前逆向给出解题过程
从后往前推,假设1~3号提出方案后都没被接收,也就是1,2,3都喂了鲨鱼,只剩下4号和5号。这时4号知道5号一定会投反对票,让4号喂鲨鱼(这时5号只能获得自己的一票,没有超过人数的一半),然后5号独吞金币。所以4号要想活命,必须不能让3号喂鲨鱼,也就是4号必定会支持3号。
3号也能明白4号一定会支持自己,所以当剩下3,4,5三个人的时候,三号提出的方案会是:100,0,0。即3号独吞掉100个金币,但3号依旧可以获得自己和4号的的票,获得了超过一半的票数。
2号推测得知3号的方案之后,会尝试为自己争取更多的票数,在2,3,4,5存活的时候,2号提出分配方案:98,0,1,1。这种分配方案下,4号,5号分到的金币比之前的0枚金币要多,所以4号和5号一定会支持2号,在加上2号自己的票,2号的这种分配方案可以得到3票的支持,超过存活人数一半的票数。
1号的知2号的分配方案之后,必然不会让自己喂鲨鱼啊。1号会尝试去争取超过一半的票数,即1号在保证自己不会被喂鲨鱼的前提下尽量让自己得到更多的金币。1号可以有以下两种方案:97,0,1,2,0或97,0,1,0,2。1号的这种方案可以获得3票(超过一半的票数):自己、三号和四号或者5号的支持。
到这里问题就彻底明朗了,看到问题的第一眼可能会感觉无从下手,或者随便蒙一个答案,亦或是以为第一个提出方案的人最容易被喂鲨鱼。细细分析后得知:第一个提出方案的人才是最后的赢家。
1.1 给你一个有序整数数组,数组中的数可以是正数、负数、零,请实现一个函数,这个函数返回一个整数:返回这个数组所有数的平方值中有多少种不同的取值。
给你一个有序整数数组,数组中的数可以是正数、负数、零,请实现一个函数,这个函数返回一个整数:返回这个数组所有数的平方值中有多少种不同的取值。举例:
-
nums = {-1,1,1,1},
那么你应该返回的是:1。因为这个数组所有数的平方取值都是1,只有一种取值 -
nums = {-1,0,1,2,3}
你应该返回4,因为nums数组所有元素的平方值一共4种取值:1,0,4,9
在往下看之前,请先进行思考,如果当时是你在面试,你会给出什么样的结题思路?下面会给出两种解法,最优解:时间复杂度:O(n)、空间复杂度O(1)。无论有没有思路,在往下看之前一定要有自己的思考。
分析:
方法一:暴力法,先算平方和,保存在一个数组中,然后使用集合统计不同。
方法二:集合保存平方和。直接先遍历一次得到平方和,将平方和放入集合中,输出集合的大小。时间复杂度为O(n),空间复杂度为O(n).
方法三:以上两种方法都没有使用到数组有序,需要计算的是不同的平方和,那么平方和相同时有两种情况,一:两个元素是相邻元素,元素值本身相同;二:两个元素绝对值相等;对于第一种情况可以直接比较是否与相邻元素相等,相等时不计数;对于第二种情况利用数组有序的条件,使用双指针分别指向数组的头和尾,相等时不计数。两指针向中间移动。
1.2 一个环有10个节点,编号0-9。从0点出发,走N步又能回到0点,共有多少种走法?
思路(动态规划)
我们可以想到,再回到0点可以从右面回来,也可以从左面回来,即先到达旁边的一个点,看看有多少回来的方法
即可。所以运用动态规划的思想,我们可以写出递推式如下:
d(k, j) = d(k-1, j-1) + d(k-1, j+1);
d(k, j)表示从点j 走k步到达原点0的方法数,因此可以转化为他相邻的点经过k-1步回到原点的问题,这样将
问题的规模
缩小.由于是环的问题, j-1, j+1可能会超出 0到n-1的范围,因此,我们将递推式改成如下:
d(k, j) = d(k-1, (j-1+n)%n) + d(k-1, (j+1)%n);
因为问题从走k步转化为走k-1步的问题,所以在写程序的时候我们就按照k从0开始递增的循环写,这样当计算第k步的
时候可以直接使用k-1步的结果。
//n 代表点的个数,k代表bushu
func GetSteps(n int, k int) int {
if n == 0 {
return 1
}
if n == 2 {
if n%2 == 0 {
return 1
} else {
return 0
}
}
var dp [100][100]int
dp[0][0] = 1
for i := 1; i < n; i++ {
dp[0][i] = 0
}
for j := 1; j <= k; j++ {
for i := 0; i < n; i++ {
dp[j][i] = dp[j-1][(i-1+n)%n] + dp[j-1][(i+1)%n]
}
}
return dp[k][0]}1.3 一个乱序数组,求第K大的数。排序方式使用字典序。
1.4 一棵二叉树,求最大通路长度。(即最大左右子树高度之和)
1.5 进程和线程的区别,使用线程真的能节省时间?
1.6 go协程的调度方式,使用协程真的能节省时间?
1.7 水平触发边沿触发的区别?在边沿触发下,一个socket有500的数据,已读取200然后不再处理,是不是剩下的300就永远无法读取?
1.8 有函数如下,输入1,返回什么?
1.9 设计http协议,A端发送 AAAA,至少让B端知道AAAA已发送完成。
2.0 流量总入口为api_gateway,api_gateway挂了会导致全部挂挂,用什么机制增大可用性?
2.1 mysql为什么要用b+树,不用平衡二叉树做索引结构?
2.2 创建数据库索引应该怎么考虑?
2.3 使用int 做primary key和使用string 有什么优劣?
2.4 数据库分表的方法?
2.5 表结构,订单纪录如下,写一个语句,求卖的最好的 top 10 product_id。
2.6 微服务,A服务请求B服务B1接口,B1接口又请求A服务A2接口。会不会有问题?
2.7 不使用高级工具,只使用Linux自带的工具,你会如何debug?
2.8 如何预估一个mysql语句的性能?
2.9 go函数中,返回值未命名,发生了panic,但是在函数内recover了。函数返回什么值?
3.0 socket中,在tcp协议层面,数据分为10个报文发放。1-7次很顺利,第8次丢失。这次通信一定失败吗?如果第8次数据会重发,那在接收端是不是:先读取到1-7次的数据,然后读取到8-10次的数据?还是9-10次的数据会先到达?
3.1 free -h,buffers 和cached有什么不同
3.2 后台进程有什么特点,如果要你设计一个进程是后台进程,你会考虑什么
3.3 僵尸进程是什么,如果产生一个僵尸进程,如何查找僵尸进程
3.4 孤儿进程是什么
3.5 一个进程有20个线程,在某个线程中调用fork,新的进程会有20个线程吗?
3.6 tcp/ip 流量控制和拥塞控制
3.7 301/302有什么区别?应用上有什么异同。
3.8 50X相关错误码的内涵是什么?
3.9 close wait和time wait是什么?如何排查?有什么意义?
4.0 http req和resp的中数据有哪些
4.1 什么是连接的半打开,半关闭状态
4.2 假如一个业务依赖单点redis,此redis故障将导致业务不可用,如何改进
4.3 redis sharding有哪些做法
4.4 当大量数据要求用redis保存,单机单点难以满足需要,设计(换寻找)一个负载均衡的方案
4.5 当redis 采用hash做sharding,现在有8个节点,负载方案是 pos = hash(key) % 8,然后保存在pos节点上。这样做有什么好处坏处?当8个节点要扩充到10个节点,应该怎么办?有什么更方便扩充的方案吗?(一致性hash, presharding)
4.6 如何保证redis和数据库数据的一致性。比如用户名既保存在数据库,又保存在redis做缓存。有如下操作 update_db(username); update_redis(username)。但是执行update_db后故障,update_redis没有执行。有什么简单办法解决这个问题。