Given a group of n soldiers standing in a circle, numbered from 1 to n.
- Starting from soldier 1, every alternate soldier is eliminated in a clockwise direction - soldier 1 eliminates soldier 2, soldier 3 eliminates soldier 4, and so on.
- This process continues around the circle until only one soldier remains.
Find the position of the soldier who survives till the end.
Examples:
Input: n = 10
Output: 5
Explanation: 1 kills 2, 3 kills 4, 5 kills 6, 7 kills 8, 9 kills 10. Now 1 kills 3, 5 kills 7, 9 kills 1. Now 5 kills 9. Surviving position = 5.Input: n = 7
Output: 7
Explanation: 1 kills 2, 3 kills 4, 5 kills 6. Now 7 kills 1, 3 kills 5. Now 7 kills 3. Surviving position = 7.
Table of Content
[Naive Approach] Using Simulation - O(n ^ 2) Time and O(n) Space
The idea is to simulate the elimination process using a vector. We repeatedly remove every alternate soldier from the circle until only one soldier remains.
Working of Approach:
- Store all soldiers from 1 to n in a vector.
- Start from soldier 2, as soldier 1 eliminates soldier 2.
- Remove every alternate soldier and update the index circularly.
- Continue until only one soldier remains.
- Return the remaining soldier's position.
#include <iostream>
#include <vector>
using namespace std;
int findPos(int n)
{
vector<int> soldiers;
// Store soldiers from 1 to n.
for (int i = 1; i <= n; i++)
{
soldiers.push_back(i);
}
int idx = 1;
// Continue until only one soldier remains.
while (soldiers.size() > 1)
{
// Remove the current soldier.
soldiers.erase(soldiers.begin() + idx);
// Move to the next soldier circularly.
idx = (idx + 1) % soldiers.size();
}
return soldiers[0];
}
int main()
{
int n = 10;
cout << findPos(n) << endl;
return 0;
}
import java.util.ArrayList;
public class GFG {
public static int findPos(int n)
{
ArrayList<Integer> soldiers = new ArrayList<>();
// Store soldiers from 1 to n.
for (int i = 1; i <= n; i++) {
soldiers.add(i);
}
int idx = 1;
// Continue until only one soldier remains.
while (soldiers.size() > 1) {
// Remove the current soldier.
soldiers.remove(idx);
// Move to the next soldier circularly.
idx = (idx + 1) % soldiers.size();
}
return soldiers.get(0);
}
public static void main(String[] args)
{
int n = 10;
System.out.println(findPos(n));
}
}
def findPos(n):
soldiers = list(range(1, n + 1))
idx = 1
# Continue until only one soldier remains.
while len(soldiers) > 1:
# Remove the current soldier.
del soldiers[idx]
# Move to the next soldier circularly.
idx = (idx + 1) % len(soldiers)
return soldiers[0]
if __name__ == '__main__':
n = 10
print(findPos(n))
using System;
using System.Collections.Generic;
public class GFG {
public static int findPos(int n)
{
List<int> soldiers = new List<int>();
// Store soldiers from 1 to n.
for (int i = 1; i <= n; i++) {
soldiers.Add(i);
}
int idx = 1;
// Continue until only one soldier remains.
while (soldiers.Count > 1) {
// Remove the current soldier.
soldiers.RemoveAt(idx);
// Move to the next soldier circularly.
idx = (idx + 1) % soldiers.Count;
}
return soldiers[0];
}
public static void Main()
{
int n = 10;
Console.WriteLine(findPos(n));
}
}
function findPos(n) {
let soldiers = Array.from({length: n}, (_, i) => i + 1);
let idx = 1;
// Continue until only one soldier remains.
while (soldiers.length > 1) {
// Remove the current soldier.
soldiers.splice(idx, 1);
// Move to the next soldier circularly.
idx = (idx + 1) % soldiers.length;
}
return soldiers[0];
}
//Driver Code
let n = 10;
console.log(findPos(n));
Output
5
[Expected Approach] Using Josephus Formula - O(1) Time and O(1) Space
The idea is to use the Josephus problem formula for eliminating every alternate soldier.
Find the largest power of 2 not greater than n. If n = power + l, then the safe position is 2 * l + 1.
Why does this approach work?
- Let p be the largest power of 2 such that p <= n.
- When n is a power of 2, soldier 1 is always the survivor.
- Let n = p + l, where l = n - p.
- Each extra soldier shifts the survivor by 2 positions.
- Hence, the safe position is 2 * l + 1.
Therefore: Safe Position = 2 * (n - p) + 1.
Working of Approach:
- Find the largest power of 2 less than or equal to n.
- Calculate the remaining value l = n - power.
- Use the Josephus formula 2 * l + 1.
- This directly gives the position of the surviving soldier.
- No simulation or extra data structure is required.
Let us understand with an example:
Input: n = 10
- m = floor(logâ(10)) = 3, so power = 2Âģ = 8.
- n - power = 10 - 8 = 2.
- Safe position = 2 Ã 2 + 1 = 5.
Output: 5
#include <iostream>
#include <cmath>
using namespace std;
int findPos(int n)
{
// Find the largest power of 2 not greater than n.
int m = floor(log(n * 1.0) / log(2.0));
int power = pow(2, m);
// Compute the safe position using Josephus formula.
return 2 * (n - power) + 1;
}
int main()
{
int n = 10;
cout << findPos(n) << endl;
return 0;
}
import java.lang.Math;
public class GFG {
public static int findPos(int n)
{
// Find the largest power of 2 not greater than n.
int m = (int)Math.floor(Math.log(n * 1.0)
/ Math.log(2.0));
int power = (int)Math.pow(2, m);
// Compute the safe position using Josephus formula.
return 2 * (n - power) + 1;
}
public static void main(String[] args)
{
int n = 10;
System.out.println(findPos(n));
}
}
import math
def findPos(n):
# Find the largest power of 2 not greater than n.
m = int(math.floor(math.log(n * 1.0) / math.log(2.0)))
power = int(math.pow(2, m))
# Compute the safe position using Josephus formula.
return 2 * (n - power) + 1
if __name__ == '__main__':
n = 10
print(findPos(n))
using System;
class GFG {
static int findPos(int n)
{
// Find the largest power of 2 not greater than n.
int m = (int)Math.Floor(Math.Log(n * 1.0)
/ Math.Log(2.0));
int power = (int)Math.Pow(2, m);
// Compute the safe position using Josephus formula.
return 2 * (n - power) + 1;
}
static void Main()
{
int n = 10;
Console.WriteLine(findPos(n));
}
}
function findPos(n)
{
// Find the largest power of 2 not greater than n.
let m = Math.floor(Math.log(n * 1.0) / Math.log(2.0));
let power = Math.pow(2, m);
// Compute the safe position using Josephus formula.
return 2 * (n - power) + 1;
}
// Driver Code
let n = 10;
console.log(findPos(n));
Output
5