There are n people standing in a circle, numbered from 1 to n. Starting from person 1, counting proceeds in clockwise direction. In each step, exactly k-1 people are skipped, and the k-th person is eliminated from the circle. The counting then resumes from the next person, and the process continues until only one person remains.
Determine the position of the last surviving person in the original circle.
Examples:
Input: n = 5, k = 2
Output: 3
Explanation: Firstly, the person at position 2 is killed, then the person at position 4 is killed, then the person at position 1 is killed. Finally, the person at position 5 is killed. So the person at position 3 survives.Input: n = 7, k = 3
Output: 4
Explanation: The persons at positions 3, 6, 2, 7, 5, and 1 are killed in order, and the person at position 4 survives.
Table of Content
- [Naive Approach - 1] Recursively Removing Elements - O(n^2) Time and O(n) Space
- [Naive Approach - 2] Using Iterative Simulation - O(n^2) Time and O(n) Space
- [Expected Approach - 1] Using Recursive Relation - O(n) Time and O(n) Space
- [Expected Approach - 2] Iterative Mathematical Approach - O(n) Time and O(1) Space
[Naive Approach - 1] Recursively Removing Elements - O(n^2) Time and O(n) Space
We can store people in an array from 1 to n. Since counting is 0-based in the code, we use k-1 instead of k. Starting at index 0, in each step we remove the person at position: (index+(k-1)) % current size.
After removing, the recursive call continues from this new index with the reduced array. This process repeats until only one person remains, who is the survivor.
Illustration:
#include <iostream>
#include<vector>
using namespace std;
int josephusRec(vector<int> person, int k, int index){
// Base case , when only one person is left
if (person.size() == 1) { ;
return person[0];
}
// find the index of first person which will die
index = ((index + k) % person.size());
// remove the first person which is going to be killed
person.erase(person.begin() + index);
// recursive call for n-1 persons
return josephusRec(person, k, index);
}
int josephus(int n,int k){
// The index where the person which will die
int index= 0;
vector<int> person;
// fill the person vector
for (int i = 1; i <= n; i++) {
person.push_back(i);
}
return josephusRec(person,k,index);
}
int main(){
int n = 7;
int k = 3;
// (k-1)th person will be killed
k--;
cout<<josephus(n, k)<<endl;
}
import java.util.ArrayList;
public class GFG {
static int josephusRec(ArrayList<Integer> person, int k, int index) {
// Base case , when only one person is left
if (person.size() == 1) {
return person.get(0);
}
// find the index of first person which will die
index = (index + k) % person.size();
// remove the first person which is going to be killed
person.remove(index);
// recursive call for n-1 persons
return josephusRec(person, k, index);
}
static int josephus(int n, int k) {
// The index where the person which will die
int index = 0;
ArrayList<Integer> person = new ArrayList<>();
// fill the person vector
for (int i = 1; i <= n; i++) {
person.add(i);
}
return josephusRec(person, k, index);
}
public static void main(String[] args) {
int n = 7;
int k = 3;
// (k-1)th person will be killed
k--;
System.out.println(josephus(n, k));
}
}
def josephusRec(person, k, index):
# Base case , when only one person is left
if len(person) == 1:
return person[0]
# find the index of first person which will die
index = (index + k) % len(person)
# remove the first person which is going to be killed
person.pop(index)
# recursive call for n-1 persons
return josephusRec(person, k, index)
def josephus(n, k):
# The index where the person which will die
index = 0
person = []
# fill the person vector
for i in range(1, n + 1):
person.append(i)
return josephusRec(person, k, index)
if __name__ == "__main__":
n = 7
k = 3
# (k-1)th person will be killed
k -= 1
print(josephus(n, k))
using System;
using System.Collections.Generic;
class GFG {
static int josephusRec(List<int> person, int k, int index) {
// Base case , when only one person is left
if (person.Count == 1) {
return person[0];
}
// find the index of first person which will die
index = (index + k) % person.Count;
// remove the first person which is going to be killed
person.RemoveAt(index);
// recursive call for n-1 persons
return josephusRec(person, k, index);
}
static int josephus(int n, int k) {
// The index where the person which will die
int index = 0;
List<int> person = new List<int>();
// fill the person vector
for (int i = 1; i <= n; i++) {
person.Add(i);
}
return josephusRec(person, k, index);
}
static void Main() {
int n = 7;
int k = 3;
// (k-1)th person will be killed
k--;
Console.WriteLine(josephus(n, k));
}
}
function josephusRec(person, k, index) {
// Base case , when only one person is left
if (person.length === 1) {
return person[0];
}
// find the index of first person which will die
index = (index + k) % person.length;
// remove the first person which is going to be killed
person.splice(index, 1);
// recursive call for n-1 persons
return josephusRec(person, k, index);
}
function josephus(n, k) {
// The index where the person which will die
let index = 0;
let person = [];
// fill the person vector
for (let i = 1; i <= n; i++) {
person.push(i);
}
return josephusRec(person, k, index);
}
// Driver code
let n = 7;
let k = 3;
// (k-1)th person will be killed
k--;
console.log(josephus(n, k));
Output
4
[Naive Approach - 2] Using Iterative Simulation - O(n^2) Time and O(n) Space
The idea is to use an array to mark alive people. Initially, all people are alive. Starting from the first person, we count k alive persons in the circle, skipping those already eliminated. When we reach the k-th alive person, we mark them as dead.
After each elimination, counting resumes from the next alive person. We continue this process iteratively, handling the circular nature by wrapping around the array indices, until only one person remains alive.
#include <iostream>
#include<vector>
using namespace std;
int josephus(int n, int k) {
k--;
int arr[n];
// Makes all the 'n' people alive by
// assigning them value = 1
for (int i = 0; i < n; i++) {
arr[i] = 1;
}
int cnt = 0, cut = 0,
// Cut = 0 gives the sword to 1st person.
num = 1;
// Loop continues till n-1 person dies.
while (cnt < (n - 1)) {
// Checks next (kth) alive persons.
while (num <= k) {
cut++;
// Checks and resolves overflow
// of Index.
cut = cut % n;
if (arr[cut] == 1) {
// Updates the number of persons
// alive.
num++;
}
}
// Refreshes value to 1 for next use.
num = 1;
// Kills the person at position of 'cut'
arr[cut] = 0;
// Updates the no. of killed persons.
cnt++;
cut++;
// Checks and resolves overflow of Index.
cut = cut % n;
// Checks the next alive person the
// sword is to be given.
while (arr[cut] == 0) {
cut++;
// Checks and resolves overflow
// of Index.
cut = cut % n;
}
}
// Output is the position of the last
// man alive(Index + 1);
return cut + 1;
}
int main(){
int n = 7, k = 3;
cout << josephus(n, k);
return 0;
}
public class Gfg {
static int josephus(int n, int k) {
// adjust for 0-based index
k--;
int[] arr = new int[n];
// Mark all persons as alive (1 = alive)
for (int i = 0; i < n; i++) {
arr[i] = 1;
}
int cnt = 0, cut = 0, num = 1;
// Continue until n - 1 people are dead
while (cnt < (n - 1)) {
// Find the k-th alive person
while (num <= k) {
cut++;
cut = cut % n; // wrap around
if (arr[cut] == 1) {
num++;
}
}
// Reset num for next round
num = 1;
// Kill the person at index 'cut'
arr[cut] = 0;
cnt++;
cut = (cut + 1) % n; // move to next
// Skip dead persons
while (arr[cut] == 0) {
cut = (cut + 1) % n;
}
}
// Return position of survivor (1-based index)
return cut + 1;
}
public static void main(String[] args) {
int n = 7, k = 3;
System.out.println(josephus(n, k));
}
}
def josephus(n, k):
k -= 1
arr = [0]*n
for i in range(n):
# Makes all the 'n' people alive by
# assigning them value = 1
arr[i] = 1
cnt = 0
cut = 0
# Cut = 0 gives the sword to 1st person.
num = 1
while (cnt < (n - 1)):
# Loop continues till n-1 person dies.
while (num <= k):
# Checks next (kth) alive persons.
cut += 1
# Checks and resolves overflow
# of Index.
cut = cut % n
if (arr[cut] == 1):
# Updates the number of persons
# alive.
num+=1
# refreshes value to 1 for next use.
num = 1
# Kills the person at position of 'cut'
arr[cut] = 0
# Updates the no. of killed persons.
cnt += 1
cut += 1
# Checks and resolves overflow of Index.
cut = cut % n
while (arr[cut] == 0):
# Checks the next alive person the
# sword is to be given.
cut += 1
# Checks and resolves overflow
# of Index.
cut = cut % n
return cut + 1
if __name__ == "__main__":
n, k = 7, 3 #map (int, input().splut())
print(josephus(n, k))
using System;
class Gfg{
static int josephus(int n, int k){
// adjust for 0-based index
k--;
int[] arr = new int[n];
// Mark all persons as alive
for (int i = 0; i < n; i++){
arr[i] = 1;
}
int cnt = 0, cut = 0, num = 1;
// Continue until n - 1 people are dead
while (cnt < n - 1){
// Find the k-th alive person
while (num <= k){
cut++;
cut = cut % n;
if (arr[cut] == 1){
num++;
}
}
// Reset num for next round
num = 1;
// Kill the person at index 'cut'
arr[cut] = 0;
cnt++;
// move to next
cut = (cut + 1) % n;
// Skip dead persons
while (arr[cut] == 0)
{
cut = (cut + 1) % n;
}
}
// Return position of survivor (1-based index)
return cut + 1;
}
static void Main()
{
int n = 7, k = 3;
Console.WriteLine(josephus(n, k));
}
}
function josephus(n, k) {
// adjust for 0-based index
k--;
let arr = new Array(n).fill(1);
let cnt = 0, cut = 0, num = 1;
// Continue until n - 1 people are dead
while (cnt < n - 1) {
// Find the k-th alive person
while (num <= k) {
cut++;
cut = cut % n;
if (arr[cut] === 1) {
num++;
}
}
// Reset num for next round
num = 1;
// Kill the person at index 'cut'
arr[cut] = 0;
cnt++;
// move to next
cut = (cut + 1) % n;
// Skip dead persons
while (arr[cut] === 0) {
cut = (cut + 1) % n;
}
}
// Return position of survivor (1-based index)
return cut + 1;
}
// Driver code
let n = 7, k = 3;
console.log(josephus(n, k));
Output
4
[Expected Approach - 1] Using Recursive Relation - O(n) Time and O(n) Space
The Josephus problem can be solved recursively using the relation:
josephus(n,k) = (josephus(n−1,k)+k−1) % n + 1
The key idea is after each elimination, the circle shrinks, but the pattern of safe positions stays the same it’s just rotated. So if we know the safe position for n-1 people, we can shift it forward by k positions to get the safe position for n people. Repeat this shrinking-and-shifting idea until only 1 person remains, which is trivially safe.
Working:
- Base case: If there’s only 1 person, return position 1.
- Recursive call: Solve Josephus for n-1 people. This gives the safe position relative to the smaller circle.
- Adjust for the shift: The eliminated person shifts positions by k. So the safe position in the original circle is (safe_from_smaller + k-1) % n + 1.
+k-1: move forward by k steps (0-based counting).
%n: wrap around the circle.
+1: convert from 0-based to 1-based indexing.
#include <iostream>
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;
}
int main() {
int n = 7;
int k = 3;
cout << josephus(n, k);
return 0;
}
#include <stdio.h>
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;
}
int main()
{
int n = 7;
int k = 3;
printf("%d", josephus(n, k));
return 0;
}
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 = 7;
int k = 3;
System.out.println( josephus(n, k));
}
}
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
if __name__ == "__main__":
n = 7
k = 3
print(josephus(n, k))
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;
}
public static void Main()
{
int n = 7;
int k = 3;
Console.WriteLine(josephus(n, k));
}
}
function 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;
}
//Driven Code
let n = 7;
let k = 3;
console.log( josephus(n, k));
Output
4
[Expected Approach - 2] Iterative Mathematical Approach - O(n) Time and O(1) Space
We can solve this iteratively by building the solution from 1 person up to n.
- For 1 person, the safe position is obviously 1.
- When we add a new person, the safe position shifts by k (because every k-th person is eliminated), wrapping around the current circle size.
- Repeating this update until n people gives the final survivor.
#include <iostream>
using namespace std;
int josephus(int N, int k){
// Initialize variables i and ans with 1 and 0
// respectively.
int i = 1, ans = 0;
// Run a while loop till i <= N
while (i <= N) {
// Update the Value of ans and Increment i by 1
ans = (ans + k) % i;
i++;
}
// Return required answer
return ans + 1;
}
int main(){
int N = 7, k = 3;
cout << josephus(N, k) << endl;
return 0;
}
#include <stdio.h>
int Josephus(int N, int k){
// Initialize variables i and ans with 1 and 0
// respectively.
int i = 1, ans = 0;
// Run a while loop till i <= N
while (i <= N) {
// Update the Value of ans and Increment i by 1
ans = (ans + k) % i;
i++;
}
// Return required answer
return ans + 1;
}
int main(){
int N = 7, k = 3;
printf("%d", Josephus(N, k));
return 0;
}
class GFG {
public static int josephus(int N, int k) {
// Initialize variables i and ans with 1 and 0
// respectively.
int i = 1, ans = 0;
// Run a while loop till i <= N
while (i <= N) {
// Update the Value of ans and Increment i by 1
ans = (ans + k) % i;
i++;
}
// Return required answer
return ans + 1;
}
public static void main (String[] args) {
int N = 7, k = 3;
int ans = josephus(N, k);
System.out.println(ans);
}
}
def josephus(n, k):
# Initialize variables i and ans with 1 and 0
# respectively.
i = 1
ans = 0
# Run a while loop till i <= N
while(i <= n):
# update the value of ans
ans = (ans + k) % i
i += 1
# returning the required answer
return ans + 1
if __name__ == "__main__":
n = 7
k = 3
result = josephus(n, k)
print(result)
using System;
class GFG{
public static int josephus(int N, int k){
// Initialize variables i and ans with 1 and 0 respectively.
int i = 1, ans = 0;
// Run a while loop till i <= N
while (i <= N){
// Update the Value of ans and Increment i by 1
ans = (ans + k) % i;
i++;
}
// Return required answer
return ans + 1;
}
static void Main(string[] args)
{
int N = 7, k = 3;
int ans = josephus(N, k);
Console.WriteLine(ans);
}
}
function josephus(n, k){
// Initialize variables i and ans with 1 and 0 respectively.
let i = 1, ans = 0;
// Run a while loop till i <= N
while(i <= n ){
// update the value of ans
ans = (ans + k) % i;
i++;
}
// Return required answer
return ans + 1;
}
// Driver code
let n = 7, k = 3;
console.log(josephus(n,k));
Output
4
Related Article: Josephus problem | Set 2 (A Simple Solution when k = 2)