思路1:
⭐ 创建一个下标为 0~n-1的数组 | 当n=5时 nums = [1 1 1 1 1] 代表下标为i的数是否已经被删除
⭐ 通过不断(外层设置一个循环)进行遍历列表 + 设置一个计算器(当nums中的元素为0则不计数) 每次到达3就将对应nums中的元素置零
⭐ (外层循环)停止条件:记录删除的元素个数 当删除的元素为n-1时,返回列表中对应1的下标。
超时
复杂度:时间复杂度O(n^2) 空间复杂度O(n)
存在问题: 题目中给定范围1 <= n <= 10^5 n^2 = 10^10 这么高的复杂度 结果造成了超时 故该方法在本题中并不适用。所以考虑一下是否有规律性的结论存在
PS:返回列表nums元素x的下标 nums.index(x) 如果x在nums中有多个 则返回的是找到的第一个的下标
def lastRemaininng1(n, m):
count = 0
delnum = 0
nums = [1] * n
while delnum < n - 1:
for i in range(n):
if nums[i] == 0:
continue
count += 1
if count == m:
delnum += 1
nums[i] = 0
count = 0
return nums.index(1)
思路2:该思路是借助力扣COOLUCAS的想法加上一些自己的想法。
问题:该问题的约瑟环问题 最开始的问题是 n个人围成一圈,第一个人从1开始报数,报m的将被杀掉,下一个人接着从1开始报。如此反复,最后剩下一个,求最后的胜利者。
分析:
我们可以把问题转化为求最后求胜利者下标的问题(只关心下标)。
⭐ 首先定义一下f(n,m)、f(n-1,m)……f(1,m)
f(n,m)指的是下标为 0,1,2,……,n-1 n个元素([A,B,C,……,Z])的约瑟环 删除第m个数字,最后剩下胜利者的下标
f(n-1,m)指的是下标为0,1,2,……,n-2 n-1个元素([A,B,C,……,Y])的约瑟环 删除第m个数字,最后剩下胜利者的下标
………………
f(1,m)指的是下标为0的 1个元素([A])的约瑟环 删除第m个数字,最后剩下胜利者的下标
⭐ 下面我们举例分析一下求解F(8,3)的过程
下标 0 1 2 3 4 5 6 7
A B C D E F G H 第一轮 C(下标2) 被杀
D E F G H A B 第二轮 F(下标5) 被杀
G H A B D E 第三轮 A(下标0) 被杀
B D E G H 第四轮 E(下标4) 被杀
G H B D 第五轮 B(下标1) 被杀
D G H 第六轮 H(下标7) 被杀
D G 第七轮 D(下标3) 被杀
G 第八轮 G(下标6) 获胜
再分析一下求解F(7,3)的过程 如果一开始其内的内容为 D E F G H A B (求下标 与其内容无关)
下标 0 1 2 3 4 5 6
D E F G H A B 第一轮 F(下标5) 被杀
G H A B D E 第二轮 A(下标0) 被杀
B D E G H 第三轮 E(下标4) 被杀
G H B D 第四轮 B(下标1) 被杀
D G H 第五轮 H(下标7) 被杀
D G 第六轮 D(下标3) 被杀
G 第七轮 G(下标6) 获胜
通过对比F(8,3) 和 F(7,3)的求解过程:我们会发现,F(7,3)其实就是求解F(8,3)时从第二轮开始的解。并且标记一下最终结果G的下标变化如下:
下标 0 1 2 3 4 5 6 7
F(8,3)=6 A B C D E F G H
F(7,3)=3 D E F G H A B
F(6,3)=0 G H A B D E
F(5,3)=3 B D E G H
F(4,3)=0 G H B D
F(3,3)=1 D G H
F(2,3)=1 D G
F(1,3)=0 G
此时的问题转化为 如果我们知道了F(i,3)的解 如何来求F(i+1,3)的解呢 让我们利用F(8,3) 和 F(7,3)看一下是否有什么规律
下标 0 1 2 3 4 5 6 7
F(8,3)=6 A B C D E F G H n=8 m=3
F(7,3)=3 D E F G H A B n=7 m=3
从F(8,3)到F(7,3)(G下标变换)的操作步骤(记住,我们只关心G的下标):
① 将整体 左移 3(m)位,并将左边溢出的 第[0,2]([0,m-1])位的元素放到其后 ②再删除最后一个元素C。 F(7,3)=(F(8,3)-3)%8 (-3相当于是左移 %8 相当于是处理溢出)
那么反推,从F(7,3)到F(8,3)的操作步骤:
① 先补上最后一个元素C, ② 再 将整体右移 3(m)位,并将右边溢出的元素放在其前。 F(8,3)=(F(7,3)+3)%8 (+3相当于是右移 %8 相当于是处理溢出)
综上,我们得到递推规律 F(n,m)=(F(n-1,m)+m)%n.
复杂度:时间复杂度O(n) 空间复杂度O(n)
def lastRemaininng2(n, m):
res = 0 # f(0)=0 如果n=5 则 0 1 2 3 4 求到f(4)即可
for i in range(2, n + 1):
res = (res + m) % i # 注意 此处 应针对i取余 因为此时的i是当下f(n)的n
return res