在计算机科学和数学中,约瑟夫斯问题(或约瑟夫斯置换)是一个理论问题。以下是问题陈述:
n人围成一圈等待执行。计数从圆的某个点开始,然后沿固定的方向围绕圆进行。在每个步骤中,将跳过一定数量的人员,然后执行下一个人员。消灭围绕圈进行(随着被处决者的撤离,圈变得越来越小),直到只有最后一个剩下的人被赋予了自由。给定总人数n和数字k,表示跳过k-1个人,第k个人被圈杀。我们的任务是选择第一个圆圈中的位置,以便您成为最后一个剩下的人,从而生存下来。
例如,如果n = 5且k = 2,则安全位置为3。首先,杀死位置2的人员,然后杀死位置4的人员,然后杀死位置1的人员。最终,位置5的人被杀死。因此,位置3的人幸存下来。
如果n = 7且k = 3,则安全位置为4。位置3、6、2、7、5、1的人员被依次杀害,位置4的人员幸存。
该问题具有以下递归结构。
josephus(n, k) = (josephus(n - 1, k) + k-1) % n + 1
josephus(1, k) = 1
第一个人(从第k个开始)被杀死后,剩下n-1个人。因此,我们将josephus(n – 1,k)称为n-1人。但是josephus(n – 1,k)返回的位置将考虑从k%n + 1开始的位置。因此,我们必须对josephus(n – 1,k)返回的位置进行调整。
以下是约瑟夫斯问题的简单递归实现。该实现仅遵循上述递归结构。
C++
#include
using namespace std;
int josephus(int n, int k)
{
if (n == 1)
return 1;
else
/* The position returned by josephus(n - 1, k)
is adjusted because the recursive call
josephus(n - 1, k) considers the
original position k % n + 1 as position 1 */
return (josephus(n - 1, k) + k-1) % n + 1;
}
// Driver Program to test above function
int main()
{
int n = 14;
int k = 2;
cout << "The chosen place is " << josephus(n, k);
return 0;
}
// This code is contributed by shubhamsingh10
C
#include
int josephus(int n, int k)
{
if (n == 1)
return 1;
else
/* The position returned by josephus(n - 1, k) is adjusted because the
recursive call josephus(n - 1, k) considers the original position
k%n + 1 as position 1 */
return (josephus(n - 1, k) + k-1) % n + 1;
}
// Driver Program to test above function
int main()
{
int n = 14;
int k = 2;
printf("The chosen place is %d", josephus(n, k));
return 0;
}
Java
// Java code for Josephus Problem
import java.io.*;
class GFG {
static int josephus(int n, int k)
{
if (n == 1)
return 1;
else
/* The position returned by josephus(n - 1, k)
is adjusted because the recursive call
josephus(n - 1, k) considers the original
position k%n + 1 as position 1 */
return (josephus(n - 1, k) + k-1) % n + 1;
}
// Driver Program to test above function
public static void main(String[] args)
{
int n = 14;
int k = 2;
System.out.println("The chosen place is " + josephus(n, k));
}
}
// This code is contributed by Prerna Saini
Python3
# Python code for Josephus Problem
def josephus(n, k):
if (n == 1):
return 1
else:
# The position returned by
# josephus(n - 1, k) is adjusted
# because the recursive call
# josephus(n - 1, k) considers
# the original position
# k%n + 1 as position 1
return (josephus(n - 1, k) + k-1) % n + 1
# Driver Program to test above function
n = 14
k = 2
print("The chosen place is ", josephus(n, k))
# This code is contributed by
# Sumit Sadhakar
C#
// C# code for Josephus Problem
using System;
class GFG {
static int josephus(int n, int k)
{
if (n == 1)
return 1;
else
/* The position returned
by josephus(n - 1, k) is
adjusted because the
recursive call josephus(n
- 1, k) considers the
original position k%n + 1
as position 1 */
return (josephus(n - 1, k)
+ k-1) % n + 1;
}
// Driver Program to test above
// function
public static void Main()
{
int n = 14;
int k = 2;
Console.WriteLine("The chosen "
+ "place is " + josephus(n, k));
}
}
// This code is contributed by anuj_67.
PHP
Javascript
C++
#include
using namespace std;
int Josephus(int, int);
int main()
{
int n, k;
cin >> n >> k;
cout << Josephus(n, k);
return 0;
}
int Josephus(int n, int k)
{
k--;
int arr[n];
for (int i = 0; i < n; i++)
{
arr[i] = 1; // Makes all the 'n' people alive by assigning them value = 1
}
int cnt = 0, cut = 0,
num = 1; // Cut = 0 gives the sword to 1st person.
while (
cnt < (n - 1)) // Loop continues till n-1 person dies.
{
while (num <= k) // Checks next (kth) alive persons.
{
cut++;
cut = cut % n; // Checks and resolves overflow of Index.
if (arr[cut] == 1)
{
num++; // Updates the number of persons alive.
}
}
num = 1; // refreshes value to 1 for next use.
arr[cut] = 0; // Kills the person at postion of 'cut'
cnt++; // Updates the no. of killed persons.
cut++;
cut = cut % n; // Checks and resolves overflow of Index.
while (arr[cut] == 0) // Checks the next alive person the sword is to be given.
{
cut++;
cut = cut % n; // Checks and resolves overflow of Index.
}
}
return cut + 1; // Output is the position of the last man alive(Index + 1);
}
/********************THIS CODE IS PRESENTED BY SHISHANK RAWAT**************************/
输出:
The chosen place is 13
时间复杂度: O(n)
使用列表的另一种方法:
一种简单的方法是创建一个列表,并在其中添加从1到n的所有值。创建一个递归函数,该函数将list,start(开始计数的位置)和k(要跳过的人数)作为参数。如果列表的大小为1,即仅剩一个人,则返回此位置。否则,从起始位置开始按顺时针方向对k个人进行计数,然后移至第k位。现在,位于第k个位置的人员将被移走,并且现在将从该位置开始计数。这个过程一直持续到只剩下一个人为止。
pseudo-code :
Josephus( list , start , k){
if list.size = 1
return list[0]
start = (start + k) % list.size
list.remove( start )
return Josephus( list, start, k)
}
范例:
Input : n = 5, k = 2
output : 3
解释 :
将列表中从1到n的所有值相加。我们将以start = 0和k = 1(0索引)调用递归函数
现在,位于1索引处的元素(2号人员)将被杀死。并将其从列表中删除。新的计数将从1索引开始,1索引处的人员被杀死,因此现在2索引处的人员(第3个人)变为1索引,并且从现在开始计数。
现在我们有4个人,从1索引(3号人)开始计数,处于kth(2索引)位置的人将被杀死。
2点索引的人(4号人)被杀,所以现在我们剩下3个人,而3点索引的人(5号人)转移到2点索引。从这里开始计数。
0索引处的人被杀,现在圈子里还剩下两个人。 1索引处的人员转移到0索引处,即人数3。
完成最后的计数,杀死处于1索引的人员,只有剩下的人员位于位置3。
这是C++中约瑟夫斯(Josephus)问题的解决方案。
对于n = 47和k = 5。
C++
#include
using namespace std;
int Josephus(int, int);
int main()
{
int n, k;
cin >> n >> k;
cout << Josephus(n, k);
return 0;
}
int Josephus(int n, int k)
{
k--;
int arr[n];
for (int i = 0; i < n; i++)
{
arr[i] = 1; // Makes all the 'n' people alive by assigning them value = 1
}
int cnt = 0, cut = 0,
num = 1; // Cut = 0 gives the sword to 1st person.
while (
cnt < (n - 1)) // Loop continues till n-1 person dies.
{
while (num <= k) // Checks next (kth) alive persons.
{
cut++;
cut = cut % n; // Checks and resolves overflow of Index.
if (arr[cut] == 1)
{
num++; // Updates the number of persons alive.
}
}
num = 1; // refreshes value to 1 for next use.
arr[cut] = 0; // Kills the person at postion of 'cut'
cnt++; // Updates the no. of killed persons.
cut++;
cut = cut % n; // Checks and resolves overflow of Index.
while (arr[cut] == 0) // Checks the next alive person the sword is to be given.
{
cut++;
cut = cut % n; // Checks and resolves overflow of Index.
}
}
return cut + 1; // Output is the position of the last man alive(Index + 1);
}
/********************THIS CODE IS PRESENTED BY SHISHANK RAWAT**************************/
如果你们喜欢它,请发表评论并帮助我做进一步的改进。
The safe position : 4