约瑟夫问题

所属作业: hw7 算法: 递归

初始化

1
2
3
lst = []
for i in range(1, N+1):
    lst.append(i)
1
lst = [i for i in range(1, N+1)]

递归写法(基本解法)

1
2
3
def joseph_list(lst: list, m: int):
    idx = (m-1) % len(lst)  # 出圈的人
    return lst[0] if len(lst) == 1 else joseph_list(lst[idx+1:] + lst[:idx], m)

模拟(每次+1)(基本解法)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def houzi(a,b):
    monkey=[]
    num=1
    if b!=1:
     for i in range(1,a+1):
        monkey.append(i)#创建出原始的猴子队伍
     while len(monkey)!=1:
        monkey.append(monkey.pop(0))#把报数的猴子移到队伍后面形成循环
        num+=1
        if num==b:#报到特定数字的猴子
            del monkey[0]#踢出队伍
            num=1#报数又重新回到1
    if b==1:
        monkey=[a]
    return monkey#返回只有猴王的列表

flag=True
while flag==True:
 a,b=map(int,input().split())

 if a==0 and b==0:
    flag=False
    break
 print(*(houzi(a,b)))

模拟优化(每次+(m-1))(基本解法)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 0 1 2 3 4 5
while True:
    n,m=map(int,input().split())
    if n==0 and m==0:
        break
    else:
        lst = [i for i in range(n)]
        cur_pos = 0
        while len(lst) != 1:
            cur_pos += m - 1 # 这里要加上m-1而不是m为什么
            cur_pos %= len(lst)
            lst.pop(cur_pos)
        print(lst[0]+1) 

数学解法(提高解法)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
def joseph_math(n,m):
    if n == 1:
        return 0     # why
    else:
        # 递归做法只需要知道两个part:
        # Part 1.
        #     [1, 2, 3, 4, 5] 能存活 [4]
        # Part 2.
        #     [1, 2, 3, 4, 5, 6] 第一次让 [5] 出去了
        # --------------------------------------
        # 那么 出去之后 圈变成了 [1, 2, 3, 4, 6]
        # 这时,从 [6] 开始数,故可以看做 [6, 1, 2, 3, 4]
        # 又因 [1, 2, 3, 4, 5] 能存活 [4]
        # 所以 [6, 1, 2, 3, 4] 能存活 [3]
        joseph_next = joseph_math(n-1,m)
        survive = (joseph_next + m) % n
        return survive

典型错误

1. 错误1

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# 0 1 2 3 4 5
while True:
    n,m=map(int,input().split())
    if n==0 and m==0:
        break
    else:
        lst = [i for i in range(n)]
        cur_pos = 0
        while len(lst) != 1:
            cur_pos += m
            cur_pos %= len(lst)
            lst.pop(cur_pos)
        print(lst[0]+1)

2. 错误2

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
num=0
while True:
    n,m=map(int,input().split())
    if n==0 and m==0:
        break
    else:
        lst=[i for i in range(1,n+1)]
        while True:
            if len(lst)==1:
                break
            else:
                a=[]
                for j in range(0,len(lst)):
                    if (j+num+1)%m!=0:
                        a.append(lst[j])
                num=(len(lst)+num)%m
                lst=a
        print(lst[0])
        num=0
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
num=0
while True:
    n,m=map(int,input().split())
    if n==0 and m==0:
        break
    elif m==1:
        print(n)
    else:
        lst=[i for i in range(1,n+1)]
        while True:
            if len(lst)==1:
                break
            else:
                a=[]
                for j in range(0,len(lst)):
                    if (j+num+1)%m!=0:
                        a.append(lst[j])
                num=(len(lst)+num)%m
                lst=a
        print(lst[0])
        num=0