第2章 面试需要的基础知识
第3章 高质量的代码
第4章 解决面试题的思路
第5章 优化时间和空间效率
第6章 面试中的各项能力
面试题62 : 圆圈中最后剩下的数字
面试题64 : 求1+2+3+…+n
第7章 两个面试案例
题目描述
0, 1, 2 ,…,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。
解题思路
实际上就是动态规划,只是这个递推式太难找了。
f(n)表示长度为n的序列,删除n-1次,最后留下元素的序号;
则f(n-1)表示长度为n-1的序列,删除n-2次,最后留下元素的序号;
我们知道 f(n)第一次删(m-1)%n,留下以((m-1)%n + 1)%(n-1)开头,长n-1的序列;
而f(n-1)留下元素的序号以0开头,因此两者的序号相差m个距离 f(n) = (f(n-1) + m) % n
具体可看LeetCode题解
这题是约瑟夫环问题,推荐博客约瑟夫环问题详解
实战
class Solution:
def LastRemaining_Solution(self, n, m):
# write code here
# n表示序列长度
if n < 1 or m < 1:
return -1
last = 0
for i in range(2, n+1):
last = (last + m) % i
return last
代码中循环为什么是从2到n呢?不应该是从n到2吗?
从递推式 f(n) = (f(n-1) + m) % n 可知,我们是已知 f(n-1) 求解 f(n)的。显然已知条件是 f(1) = 0,从已知条件推导 f(2),逐步递推就得到最后的 f(n)。
DP算法的特点是分析问题的顺序和求解顺序相反。