当前位置:   article > 正文

常见面试题总结2020秋招_问先抛者先去吃饭的概率是

问先抛者先去吃饭的概率是

1、LRU缓存机制

哈希表+双向链表,保证可以随时在头结点和尾节点进行数据插删除,同时记得更新dict哈希表中存储的key值

最新使用的程序插在双向链表的头部。

  1. class DLinkedNode:
  2. """
  3. 双链表节点
  4. """
  5. def __init__(self, key: int = 0, value: int = 0):
  6. self.prev = None
  7. self.next = None
  8. self.key = key
  9. self.value = value
  10. class LRUCache:
  11. def __init__(self, capacity: int):
  12. self.size = 0
  13. self.capacity = capacity
  14. self.cache = dict()
  15. self.head = DLinkedNode()
  16. self.tail = DLinkedNode()
  17. self.head.next = self.tail
  18. self.tail.prev = self.head
  19. def get(self, key: int) -> int:
  20. # 如果key不在cache中, 直接返回-1
  21. if key not in self.cache:
  22. return -1
  23. # 从cache中获取key对应的节点
  24. node = self.cache[key]
  25. # 移动节点到链表的头部
  26. self.move_to_head(node)
  27. # 返回节点的值
  28. return node.value
  29. def put(self, key: int, value: int) -> None:
  30. node = DLinkedNode(key, value)
  31. # 如果key不在cache中
  32. if key not in self.cache:
  33. # 且此时缓存容量已满
  34. if self.capacity == self.size:
  35. # 移除链表中最后一个节点
  36. last_node = self.remove_last()
  37. # 同时从cache中弹出最后一个节点
  38. self.cache.pop(last_node.key)
  39. # 把新节点加入到链表的头部
  40. self.add_to_head(node)
  41. # 更新cache
  42. self.cache[key] = node
  43. else:
  44. # 容量未满, 直接把新节点加入到链表头部
  45. self.add_to_head(node)
  46. # 同时更新缓存
  47. self.cache[key] = node
  48. # 缓存大小加一
  49. self.size += 1
  50. else:
  51. # 如果key在cache中, 那就不用再考虑缓存容量的影响
  52. # 把老节点cache和链表中移除
  53. old_node = self.cache.pop(key)
  54. self.remove_node(old_node)
  55. # 再把新节点加入到cache和链表中
  56. self.add_to_head(node)
  57. self.cache[key] = node
  58. def add_to_head(self, node: DLinkedNode):
  59. """
  60. 把节点加入到链表头部
  61. """
  62. next_node = self.head.next
  63. self.head.next = node
  64. node.prev = self.head
  65. node.next = next_node
  66. next_node.prev = node
  67. def remove_node(self, node: DLinkedNode):
  68. """
  69. 从链表中移除指定节点
  70. """
  71. node.prev.next = node.next
  72. node.next.prev = node.prev
  73. def move_to_head(self, node: DLinkedNode):
  74. """
  75. 把节点移动到链表头部
  76. """
  77. self.remove_node(node)
  78. self.add_to_head(node)
  79. def remove_last(self) -> DLinkedNode:
  80. """
  81. 移除链表中最后一个节点并返回
  82. """
  83. last_node = self.tail.prev
  84. self.tail.prev.prev.next = self.tail
  85. self.tail.prev = self.tail.prev.prev
  86. return last_node

2、抢红包算法实现

二倍均值法
方法实现的原理是:每次以 [最小值,红包剩余金额 / 人数 * 2] 的区间进行取值。

假设红包金额为 88.88,红包数量为 8 个,理想情况下,方法的实现效果:

第一个人领取红包金额区间为 [0.01, 88.88 / 8 * 2],即是 [0.01, 22.22] 之间随机获取金额数。假设取平均值 11.11,则剩余金额 77.77;

第二个人领取红包金额区间为 [0.01, 77.77 / 7 * 2],即是 [0.01, 22.22] 之间随机获取金额数。假设取平均值 11.11,则剩余金额 66.66;

以此类推…

  1. import random
  2. def get_packet(amount,number):
  3. res =[]
  4. person_num = number
  5. cur_amount = amount*100
  6. for _ in range(number-1):
  7. money = random.randint(1,cur_amount//person_num*2)
  8. cur_amount -= money
  9. person_num -= 1
  10. res.append(money/100)
  11. res.append(cur_amount/100)
  12. return res
  13. res = get_packet(88.88, 8)
  14. for amount in res:
  15. print('红包金额:{}'.format(amount))

3、最小生成元

如果x+x的各个数字之和得到y,就是说x是y的生成元。给出n(1<=n<=100000),求最小生成元。无解输出0.例如,n=216,121,2005时的解分别是198,0,1979.

利用打表法,提前把1到100000的最小生元给存下来,你要知道谁的最小生成元,直接输出就行了。

  1. #include<stdio.h>
  2. #define N 10005
  3. int a[N]
  4. int main()
  5. {
  6. int n;
  7. scanf("%d",&n);
  8. for(int i = 1;i<=10000;i++)
  9. {
  10. int x = i,y =i;
  11. while(y>0)
  12. {
  13. x += y%10;
  14. y/=10;
  15. }
  16. if (a[x] ==0)
  17. a[x] = i;
  18. }
  19. printf("%d",a[n]);
  20. return 0 ;
  21. }

4、python实现一段文本中单词个数的统计

  1. string = "hello world nihao world hey hello java world hi python yeoman word"
  2. list1 = string.split()
  3. set1 = set(list1)
  4. list2 = list(set1)
  5. dir2 = {}
  6. for i in range(len(list2)):
  7. dir2[list2[i]] = 0
  8. for j in range(len(list1)):
  9. if list1[j] == list2[i]:
  10. dir2[list2[i]]+=1
  11. print(dir2)
  12. ========
  13. from collections import Counter
  14. list1 = sentence.split()
  15. dir1 = Counter(list1)

5、辗转相除法求最大公约数,求分数之和

  1. def sum(a,b,c,d):
  2. fenzi = b*c +a*d
  3. fenmu = a*c
  4. a =fenmu
  5. b =fenzi
  6. c = a% b
  7. while(c):
  8. a = b
  9. b = c
  10. c = a % b
  11. fenzi /= b
  12. fenmu /= b
  13. return fenzi,fenmu
  14. print(sum(2,1,3,1))

6、十进制转换

  1. def divbase(num,base):
  2. stack = []
  3. digital = "0123456789ABCDEF"
  4. while num >0:
  5. temp = num %base
  6. stack.append(temp)
  7. num = num//base
  8. #print(stack[::-1])
  9. res=""
  10. while stack:
  11. #print(stack[-1])
  12. if base>10:
  13. res +=str(digital[stack[-1]])
  14. stack.pop()
  15. else:
  16. res +=str(stack[-1])
  17. stack.pop()
  18. return res
  19. print(divbase(43,16))

7、两根香,一根烧完1小时,如何测量15分钟

---->开始时一根香两头点着,一根香只点一头,两头点着的香烧完说明过去了半小时,这时将只点了一头的香另一头也点着,从这时开始到烧完就是15分钟。

8、写一个函数,求平方根,函数参数为目标数字和精度,测试案例 fn(4.1,0.001) fn(501.1,0.001) fn(0.045,0.001)

  1. def mySqrt(target,g):
  2. l = float(1)
  3. r = float(target)
  4. mid = float()
  5. while r-l>g:
  6. mid = (l+r)/2
  7. if mid * mid > target:
  8. r = mid
  9. else:
  10. l = mid
  11. return (l+r)/2
  12. print(mySqrt(4.1,0.001))

9、给定一个 0-4随机数生成器 如何生成0-6随机数

rand6() = {rand4() * 5 + rand4() }<=20?x/3:loop

我们可以想,第一个rand6()产生一个0~6范围的随机数a,第二个rand6()产生一个0~6范围的随机数b,如果(a, b)这一对数可以确定一个唯一的数,从而可以产生的49个数(a和b都有7种可能,则(a, b)确定的数就有7*7=49种可能)都是等概率的。这就相当于有一个二维坐标系,X轴和Y轴上都可以取0~6的数,对于取x=a,y=b可以确定一个唯一的点(a, b)。0-6生成0-9随机数

想到这个就是我们的关键,接下来就是想办法构造函数使得产生的每个数都是唯一的。我们不难想到把第一个rand6()产生的随机数a放在个位上,而把第二个rand6()产生的随机数b放在十位上,所有可能为:00~06,10~16,20~26,30~36,40~46,50~56,60~66。很容易看出这些就是7进制数,所以我们用rand6()*7+rand6()就能生成0~49范围的随机数,而且每个数产生的概率相等,都是1/49。产生40~49之间的随机数时不保留而重新产生一个新的随机数,这样产生0~39之间的数也是等概率的,仍然都是1/49,对于产生的数我们记为r(0<= r <=39),则 r/4 即可返回0~9范围的数。而且 r 取0~3这四个数时 r/4 返回0,r 取4~7这四个数时 r/4 返回1,……,r 取36~39这四个数时 r/4 返回9。因此返回0~9范围的每个数字的概率都是4/49,满足等概率。

10、海盗分金币

问题描述:

        五个极其聪明的海盗抢到100颗宝石,每一颗宝石都一样大小和价值连城。他们决定以抽签投票的方式来分配这些宝石:有(1、2、3、4、5)五个号码,每人抽取一个。首先,由1号提出分配方案,然后大家举手表决,当且仅当超过半数的人同意时,按照他的分配方案 进行分配,否则将被扔进海里喂鲨鱼。如果1号死后,再由2号提出分配方案,规则如前所述,以此类推。

问:第一个海盗提出怎样的分配方案才能使自己的收益最大化?为什么?

解答:https://blog.csdn.net/guo_jia_liang/article/details/53957393

答案分析: 1号海盗分给3号1枚金币,4号或5号2枚金币,自己则独得97枚金币,即分配方案为(97,0,1,2,0)或(97,0,1,0,2)。

11、场景题:一个硬币,正面概率0.7,反面概率0.3,怎么掷能让两个人公平的喝到水

---->抛两次,先正后反A喝,先反后正B喝

某一次抛出硬币,正面向上的概率是p,反面向上的概率是1 - p,当p不等于0.5时,这两个事件的概率就不一样了。怎么能凑出等概率呢?还是要利用概率的加法和乘法法则。这里用乘法,也就是连续的独立事件。

连续抛两次硬币,正反面的出现有四种情况,概率依次为:

  1. 两次均为正面:p * p
  2. 第一次正面,第二次反面:p * (1 - p)
  3. 第一次反面,第二次正面:(1 - p) * p
  4. 两次均为反面:(1 - p) * (1 - p)

这不,中间两种情况的概率是完全一样的。于是问题的解法就是连续抛两次硬币,如果两次得到的相同则重新抛两次;否则根据第一次(或第二次)的正面反面情况,就可以得到两个概率相等的事件。

 

12、64匹马,8个跑道,选跑最快的4匹马需要比赛多少次

 

13、概率:两个人轮流抛硬币,先抛到正面的赢,问先抛的人赢的概率

设先抛先吃的概率为p1, 后抛先吃的概率为p2

那么有:

p1 = 1/2 + 1/2 * p2

p1 + p2 = 1

解方程可得,

p1 = 2/3

14、2个鸡蛋扔100层楼,求最坏情况下所需次数

  • 1、只有一个小球怎么办,遍历,O(n)的时间复杂度
  • 2、2个鸡蛋的时候具体来说,假设我们每10层楼扔第一个蛋,当在10x层扔坏,我们从10(x-1) 开始顺序扔到 10x。那么最坏情况下需要 10 + 9 = 19. 10 是第一个蛋的,9是第二个蛋的次数。按照这个方法,当第一个蛋达到最坏情况时,比第二个刚好多一。这样是平衡的。问题在于,如果第一个蛋在10就碎了,那么第二个蛋要扔9次,总共10次。两种最坏情况不平衡。也就是说,我们希望动态地调整扔蛋一的层数,使得(蛋一+蛋二)的总和平均。

那么考虑这个方法:假设蛋一第一次扔在X层,第二次扔在比原来高 X-1层,... 高2, 高1,使得X+(X-1)+...+2+1=100,那么最坏情况总的次数就是:

如果在第X层就碎,那么蛋二最坏情况要扔X-1,所以总数是 1+X-1=X
如果在X+(X-1)碎,那么蛋二最坏情况要扔 X-2,所以2+X-2=X
...1+2+3+4+......+14>100

解得 X = 14.

⼆分查找排除楼层的速度⽆疑是最快的, 那⼲脆先⽤⼆分查找, 等到只剩 1 个鸡蛋的时候再执⾏线性扫描, 这样得到的结
果是不是就是最少的扔鸡蛋次数呢?
很遗憾, 并不是, ⽐如说把楼层变⾼⼀些, 100 层, 给你 2 个鸡蛋, 你在 50层扔⼀下, 碎了, 那就只能线性扫描 1〜49 层了, 最坏情况下要扔 50 次。

如果不要「⼆分」 , 变成「五分」 「⼗分」 都会⼤幅减少最坏情况下的尝试次数。 ⽐⽅说第⼀个鸡蛋每隔⼗层楼扔, 在哪⾥碎了第⼆个鸡蛋⼀个个线性扫描, 总共不会超过 20 次​。
最优解其实是 14 次。

15、两个很大的数据集存着URL,找到两个数据集共有的URL

参考链接:https://www.jianshu.com/p/f9f5b66f8a32

 

1)首先我们最常想到的方法是读取文件a,建立哈希表(为什么要建立hash表?因为方便后面的查找),然后再读取文件b,遍历文件b中每个url,对于每个遍历,我们都执行查找hash表的操作,若hash表中搜索到了,则说明两文件共有,存入一个集合。

(2)但上述方法有一个明显问题,加载一个文件的数据需要50亿*64bytes = 320G远远大于4G内存,何况我们还需要分配哈希表数据结构所使用的空间,所以不可能一次性把文件中所有数据构建一个整体的hash表。所以虽然可行,但是无法满足需求。

(3)针对上述问题,我们分治算法的思想。

step1:遍历文件a,对每个url求取hash(url)%1000,然后根据所取得的值将url分别存储到1000个小文件(记为a0,a1,...,a999,每个小文件约300M),为什么是1000?主要根据内存大小和要分治的文件大小来计算,我们就大致可以把320G大小分为1000份,每份大约300M(当然,到底能不能分布尽量均匀,得看hash函数的设计)

step2:遍历文件b,采取和a相同的方式将url分别存储到1000个小文件(记为b0,b1,...,b999)(为什么要这样做? 文件a的hash映射和文件b的hash映射函数要保持一致,这样的话相同的url就会保存在对应的小文件中,比如,如果a中有一个url记录data1被hash到了a99文件中,那么如果b中也有相同url,则一定被hash到了b99中)

所以现在问题转换成了:找出1000对小文件中每一对相同的url(不对应的小文件不可能有相同的url)

step3:因为每个hash大约300M,所以我们再可以采用(1)中的想法

16、多叉树的最长路径

二叉树的最长路径的进阶版:https://blog.csdn.net/wangbaochu/article/details/53870330

  1. #include<iostream>
  2. #include<vector>
  3. #include<algorithm>
  4. int maxDistance = 0;
  5. std::vector<std::vector<int> > G(100001);//存储边信息
  6. inline void AddEdge(int v, int s)//把结点v和s关联
  7. {
  8. G[v].push_back(s);
  9. G[s].push_back(v);
  10. }
  11. int LastOrder(int pre, int cur)
  12. {
  13. int first = 0, second = 0;//最大值和次大值
  14. for (size_t i = 0; i < G[cur].size(); ++i)
  15. {
  16. if (G[cur][i] == pre)//一直向下,不着重复的边
  17. continue;
  18. int temp = LastOrder(cur, G[cur][i]);//向下找
  19. if (temp>first)
  20. {
  21. second = first;
  22. first = temp;
  23. }
  24. else if (temp > second)
  25. {
  26. second = temp;
  27. }
  28. }
  29. //注意:在以当前结点为根节点的子树中,最远两个结点的距离为first+second。
  30. maxDistance = std::max(maxDistance, first + second);
  31. return first + 1; //只返回当前子树的最大深度,父结点只需要知道子树的最大深度。
  32. }
  33. int main()
  34. {
  35. int N;
  36. std::cin >> N;
  37. int Ai, Bi;
  38. for (int i = 1; i < N; ++i)
  39. {
  40. std::cin >> Ai >> Bi;
  41. AddEdge(Ai, Bi);
  42. }
  43. LastOrder(0, 1);
  44. std::cout << maxDistance;
  45. return 0;
  46. }

17、给定一个有向无环图,按拓扑排序的顺序输出节点

  1. #使用循环进行拓扑排序
  2. def topoSort(G):
  3. #初始化计算被指向节点的字典
  4. cnt=dict((u,0) for u in G.keys())
  5. #若某节点被其他节点指向,该节点计算量+1
  6. for u in G:
  7. for v in G[u]:
  8. cnt[v]+=1
  9. #收集被指向数为0的节点,此时Q只有一个节点,即起始节点a
  10. Q=[u for u in cnt.keys() if cnt[u]==0]
  11. #记录结果
  12. seq=[]
  13. while Q:
  14. s=Q.pop()
  15. seq.append(s)
  16. for u in G[s]:
  17. cnt[u]-=1
  18. if cnt[u]==0:
  19. Q.append(u)
  20. return seq
  21. #有向无环图的邻接字典
  22. G={
  23. 'a':{'b','f'},
  24. 'b':{'c','d','f'},
  25. 'c':{'d'},
  26. 'd':{'e','f'},
  27. 'e':{'f'},
  28. 'f':{}
  29. }

20、抛硬币10000次,7000次朝上,求置信区间(中心极限定理)

这种属于二项分布的检验,会有2个数值方向。当概率p<0.626时,P(X<=70)>=0.9506(此时可以理解为概率过小,100次里不超过70次正面的可能性很大);当概率p>=0.775时,P(X>70)=1-0.0502=0.9498(此时可以理解为概率过大,100次里超过70次正面的可能性很大);所以当概率p在[0.626,0.775)区间内,在95%的置信区间(有95%把握)判断硬币出现正面的概率区间为[0.626,0.775)


可以得到对应的概率值,然后取计算Z值,可以得到95%置信区间对应的两边端点值

https://pic1.zhimg.com/80/23d96ba0bcafd47aa100b7caa4522ec4_720w.jpg?source=1940ef5c


 

其中95置信区间下u一般为1.96

 

 

 

 

 

 

 

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/162640
推荐阅读
相关标签
  

闽ICP备14008679号