1. 题目
0,1,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。
例如,0、1、2、3、4这5个数字组成一个圆圈,从数字0开始每次删除第3个数字,则删除的前4个数字依次是2、0、4、1,因此最后剩下的数字是3。
2. 解题思路
这道题是简单,我是万万没想到的。
其实本题是著名的约瑟夫环问题
。
2.0 暴力法
就按照题目的思路,用一个变量计数,每到m之后,删除数组中的一个元素,直到只剩一个元素。但是超时了。
2.1 数学法
3. 代码实现
3.0 暴力法
class Solution:
def lastRemaining(self, n: int, m: int) -> int:
"""
1. 暴力法, 超时
"""
record = list(range(n)) # 记录元素
count = 0
while len(record) > 1:
i = 0
while i < len(record) and len(record)>1:
count += 1
if count == m:
del record[i]
count = 0 # 重置为0
else:
i += 1
return record[0]
3.1 数学法
class Solution:
def lastRemaining(self, n: int, m: int) -> int:
"""
1. 暴力法, 超时
2. 数学法,题解都没看懂。。
"""
ans = 0;
# 最后一轮剩下2个人,所以从2开始反推
for i in range(2, n+1):
ans = (ans + m) % i
return ans
4. 总结
算法这东西要是涉及到数学知识,那么真的是难。
5. 参考文献
[1] 剑指offer丛书
[2] 剑指Offer——名企面试官精讲典型编程题