📅  最后修改于: 2023-12-03 15:10:03.594000             🧑  作者: Mango
在一张卡上,有数字从0到n-1依次排列。现在对这张卡执行给定的操作,具体操作描述如下:
从卡上的第一个数字开始,每次删除第m个数字。
删除的数字不再保留,下一个数字继续从卡的第一个数字开始数。
重复上述操作,直到卡上只剩下一个数字为止。
你的任务是编写一个函数,返回执行上述操作后,卡上最后剩下的数字。
这是一道经典的问题,有多种解法。
我们可以用链表来模拟整个过程。首先把0~n-1的数字放入链表中,然后从头开始遍历链表,每经过m-1个节点就删除它。删除节点后继续从头开始遍历链表,直到链表中只剩下一个节点为止。
也可以用递推公式解决这个问题。如果我们用f(n,m)代表最后留下的数字的下标,那么有下面的递推关系:
f(n, m) = (f(n-1,m) + m) % n
这个公式的意义是,在n个数字中,每次删除第m个数字,最后剩下的数字的位置等于在n-1个数字中删除第m个数字最后剩下的数字的位置再往后移m个位置。这是一个递归的结构,当n=1时,递归结束,方程的解就是0。
class Node:
def __init__(self, val=None, next=None):
self.val = val
self.next = next
def lastRemaining(n: int, m: int) -> int:
# 构建链表
head = Node(0)
pre = head
for i in range(1, n):
node = Node(i)
pre.next = node
pre = pre.next
# 进行删除操作,直到链表中只剩一个节点
while head.next != head:
for i in range(m-1):
head = head.next
head.next = head.next.next
return head.val
def lastRemaining(n: int, m: int) -> int:
f = 0
for i in range(2, n+1):
f = (f + m) % i
return f
不论使用哪种方式,本题都是一道简单的数学题,但需要注意边界条件和细节问题。使用链表来模拟可以避免出现integer overflow的问题,但需要注意内存的消耗。而用递推公式则可以更为简洁地解决问题,但需要考虑清楚每个变量的含义,以免出现错误的递推关系。