Josephus Problem

Josephus Problem

Problem Statement

There are N people standing in a circle numbered from 1 to N. Also given an integer K. First, count the K-th number starting from the first one and delete it. Then K numbers are counted starting from the next one and the K-th one is removed again, and so on. The process stops when one number remains. The task is to find the last number.

Examples:

  • Input: N = 6, K = 2
  • Output: 5

Explanation:


Recursive Approach

A simple approach to solve this problem is to find the position of the step which would be called after each execution.

Therefore, given N persons, and skipping K persons during their deletion, N – 1 persons will be left. Therefore, we need to call the recursive function for N – 1 and K for the next iteration.

Now, for each remaining circle after execution, we need to find the last remaining person present i.e. if Kth person is executed, K+1th will be the next starting safe point the recursive call. Therefore, to keep a track of the position, perform K%N + 1.

The recursive function would be:

josephus(N, K) = (josephus(N – 1 , K) + K – 1) % N + 1.

You can also observe a pattern as follows:

Algorithm

  • If N  == 1, return 1. This is the termination condition for the function.
  • Else, return (josephus(N – 1 , K) + K – 1) % N + 1.

C++ Code

int josephus(int N, int K) {
  if (N == 1)
    return 1;
  else
    return (josephus(N - 1, K) + K - 1) % N + 1;
}

Java Code

 static int josephus(int N, int K) {
  if (N == 1)
    return 1;
  else
    return (josephus(N - 1, K) + K - 1) % N + 1;
}

Python Code

def josephus(N, K):
 
    if N == 1:
        return 1
    else:
        return (josephus(N - 1, K) + K - 1) % N + 1
  • Time Complexity: O(N)
  • Space Complexity: O(N), depth of the recursion tree.

Using List – Approach 2

In this approach, initialize a list containing all integers from 1 to N and delete every Kth node until one element is left.

Algorithm

  • Create a list containing integers from 1 to N.
  • Create a recursive function which deletes every Kth element from the list in each iteration in the clockwise direction.
  • Continue repeating the above steps until only one element is left.

Implementation of the Approach:

C++ Code

void Josh(vector < int > person, int k, int index) {
  if (person.size() == 1) {
    cout << person[0] << endl;
    return;
  }
  index = ((index + k) % person.size());
  person.erase(person.begin() + index);
  Josh(person, k, index);
}
 
solve(n, k) {
  k--;
  int index = 0;
 
  vector < int > person;
  for (int i = 1; i <= n; i++) {
    person.push_back(i);
  }
 
  Josh(person, k, index);
}

Java Code

 static void Josh(ArrayList < Integer > person, int k, int index) {
  if (person.size == 1) {
    System.out.println(person.get(0));
    return;
  }
  index = ((index + k) % person.size());
  person.remove(index);
  Josh(person, k, index);
}
 
solve(int N, int K) {
  K = K - 1;
  int index = 0;
 
  Arraylist < Integer > person;
  for (int i = 1; i <= N; i++) {
    person.push_back(i);
  }
 
  Josh(person, K, index);
}

Python Code

def Josh(person, k, index):
    if len(person) == 1:
        print(person[0])
        return
 
    index = (index + k) % len(person)
    person.pop(index)
    Josh(person, k, index)
 
 
def solve(N, K):
 
    K = K - 1
    index = 0
 
    persons = [0] * (N)
    for i in range(1, N + 1):
        person.append(i)
 
    Josh(person, K, index)
  • Time Complexity: O(N), where N is total persons.
  • Space Complexity: O(N), a list of size N, is used.

Special Case: K = 2

For K = 2, the problem becomes much easier to solve.

In case, N is even, first all even positions will get deleted. Then, the remaining N / 2 remains. Therefore, the answer for the remaining N can be found from the answer for N / 2 by multiplying it with 2 and subtracting 1 i.e. shifting the positions.

The answer for even N can obtained as –

josephus(2 * N, 2) =  josephus(N, 2) – 1

Similarly, In case, N is odd, first, all even positions will get deleted. Then, remaining (N – 1) / 2 remains. Therefore, the answer for the remaining N can be found from the answer for (N – 1) / 2 by multiplying it with 2 and subtracting 1 i.e. shifting the positions.

The answer for even N can obtained as –

josephus(2 * N + 1, 2) =  josephus(N, 2) – 1

From the above relations, both can be merged and can be written as –

josephus(N, 2) = 1 + 2 * (N – 2 ^(floor(log2(N))

C++ Code

int josephus(int N) {
  int p = 1;
  while (p <= N)
    p *= 2;
 
  return (2 * N) - p + 1;
}

Java Code

 static int josephus(int N) {
  int p = 1;
  while (p <= N)
    p *= 2;
 
  return (2 * N) - p + 1;
}

Python Code

def josephus(N):
    p = 1
    while p <= N:
        p *= 2
 
    return (2 * N) - p + 1
  • Time Complexity: O(logN), where N is the total steps.
  • Space Complexity: O(1), as no extra s[ace is used.

Practice Question


FAQs

Q.1: What data structure is used in solving the Josephus problem?

Ans: A list can be used to solve the Josephus problem, which initially contains all the integers from 1 to N.

Q.2: How to solve the Josephus problem?

Ans: The Josephus problem can be solved using recursion. For each iteration, recursively delete the Kth position until only one person is left.

Previous Post

NGINX vs Apache: What’s The Difference?

Next Post

10 Best Artificial Intelligence Books (2023)

Exit mobile version