N个数字排成一个圆环,每次删除第n个数字,求最后剩下的一个数字。
经典的约瑟夫环问题,例如,N = [0,1,2,3,4,5,6,7,8,9],每次删除第3个数字,每次删除后,N的数值如下:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[3, 4, 5, 6, 7, 8, 9, 0, 1]
[6, 7, 8, 9, 0, 1, 3, 4]
[9, 0, 1, 3, 4, 6, 7]
[3, 4, 6, 7, 9, 0]
[7, 9, 0, 3, 4]
[3, 4, 7, 9]
[9, 3, 4]
[9, 3]
[3]
设f(m,n) 为结果的下标位置,即f(1,3) = 0,则有:
f(1,3) = 0
f(2,3) = 1
f(3,3) = 0
……
f(8,3) = 6
f(9,3) = 1
f(10,3) = 3
表达式可以转换为:
f(2,3) = (f(1,3) + 3 ) % 2
……
f(9,3) = (f(8,3) + 3 ) % 9
f(10,3) = (f(9,3) + 3) % 10

res = 0
N = 10
n = 3
for i in range(2,N+1):
    res = (res + n) % i
print(res)

扩展:N个数字排成一个圆环,每次删除第n个数字,求最后剩下的m个数字。
可通过递归的方式,每次删除后给数组重新排序,直到数组最后剩余m个数字。

# 每次删除第n个数,求最后剩余的m个数
def lastRemaining(arr,n,m):
    if len(arr) == m:
        return arr
    else:
        if n >= len(arr) and n % len(arr) == 0:
            n1 = len(arr)
        elif n > len(arr):
            n1 = n % len(arr)
        else:
            n1 = n
        arr[:] = arr[n1:] + arr[:n1-1]
        return lastRemaining(arr,n,m)
arr = []
for i in range(0,10):
    arr.append(i)
print(lastRemaining(arr,4,2))
>>> [4, 5]

每次递归重组的数列如下:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[4, 5, 6, 7, 8, 9, 0, 1, 2]
[8, 9, 0, 1, 2, 4, 5, 6]
[2, 4, 5, 6, 8, 9, 0]
[8, 9, 0, 2, 4, 5]
[4, 5, 8, 9, 0]
[0, 4, 5, 8]
[0, 4, 5]
[4, 5]

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐