Problem
There are n
friends that are playing a game. The friends are sitting in a circle and are numbered from 1
to n
in clockwise order. More formally, moving clockwise from the ith
friend brings you to the (i+1)th
friend for 1 <= i < n
, and moving clockwise from the nth
friend brings you to the 1st
friend.
The rules of the game are as follows:
- Start at the
1st
friend. - Count the next
k
friends in the clockwise direction including the friend you started at. The counting wraps around the circle and may count some friends more than once. - The last friend you counted leaves the circle and loses the game.
- If there is still more than one friend in the circle, go back to step
2
starting from the friend immediately clockwise of the friend who just lost and repeat. - Else, the last friend in the circle wins the game.
Given the number of friends, n
, and an integer k
, return the winner of the game.
Josephus circle
This is also called Josephus circle:
N people have decided to elect a leader by arranging themselves in a circle and eliminating every Mth person around the circle, closing ranks as each person drops out. Find which person will be the last one remaining (with rank 1).
Examples
Example 1:
|
|
Example 2:
|
|
Solution
Method 1 - Brute Force
We can do following:
- Use a list to represent the friends sitting in a circle.
- Use a loop to simulate the process of eliminating every kth friend until only one friend remains.
- Calculate the index of the next friend to be eliminated using
(currIdx + k - 1) % friends.size()
. This ensures the count wraps around the circle. - Remove the friend at
currIdx
from the list.
- Calculate the index of the next friend to be eliminated using
Code
|
|
Complexity
- ⏰ Time complexity:
O(n^2)
, wheren
is number of friends.- Adding the friends take
O(n)
time - Now, we remove
n - 1
friends from list, and removing 1 friend from list by value takesO(n)
. So, it should beO((n-1)*n)
⇨O(n^2)
.
- Adding the friends take
- 🧺 Space complexity:
O(n)
for storing n friends
Method 2 - Using Queue
Instead of using list, we use the queue to store the friends.
- Use a queue to represent the friends sitting in a circle.
- Now, to eliminate
n - 1
friends, we can run the loop till queue size is 1, OR run loopn - 1
- Now, each time we start from first friend, and count k. We send
k - 1
friends to the end of queue - But kth friend will eliminated from list
- Now, each time we start from first friend, and count k. We send
[!NOTE] Note For the interview purpose, this method may not be required, until it is asked as a mathematical problem.
Here is the video explanation:
Dry Run
|
|
Code
|
|
Complexity
- ⏰ Time complexity:
O(n*k)
- Adding the friends take
O(n)
time - Then, we run elimination round n - 1 times, for k friends which takes
O(n*k)
- Adding the friends take
- 🧺 Space complexity:
O(n)
Method 3 - Mathematics and recursion
Lets convert it to recursive function. Let’s assume we have f(n,k)
which will gives us one remaining after nth
turn in a group of nth people if we count k person at each turn. Lets assume 0-based index.
Then, the base case is n = 1 - If there is only one person left, the winner’s index is 0 (since 0-based index).
|
|
For generic n
:
|
|
Our answer will be, as this is 1-based output.
|
|
Dry Run
We start with g(5, 2) = f(5, 2) + 1
.
f(5,2)
calls f(4,2)
calls f(3,2)
calls f(2,2)
calls f(1,2)
.
Now, f(1,2)
returns 0.
We can unwind the recursion stack now:
|
|
Now, we adjust for 1-based indexing:
|
|
Code
|
|
Complexity
- ⏰ Time complexity:
O(n)
- 🧺 Space complexity:
O(n)
for using recursion stack
Method 4 - Mathematics and iterative
Code
|
|
Complexity
- ⏰ Time complexity:
O(n)
- 🧺 Space complexity:
O(1)