CSES Solutions - Josephus Queries
Last Updated :
28 Apr, 2024
Improve
Consider a game where there are n children (numbered 1,2,...n) in a circle. During the game, every second child is removed from the circle, until there are no children left.
Your task is to process q queries of the form: "when there are n children, who is the kth child that will be removed?"
Example:
Input: totalChildren = 7, kthChild = 1;
Output: 2
Explanation:
- Initial children: 1 2 3 4 5 6 7
- After 1st removal: 2 is removed
Input: totalChildren = 7, kthChild = 3;
Output: 6
Explanation:
- Initial children: 1 2 3 4 5 6 7
- After 1st removal: 2 is removed
- After 2nd removal: 4 is removed
- After 3rd removal: 6 is removed
Approach:
The idea is to use a recursive function let say calculateRemovedChild () to solve the problem.
- Base Case: If there’s only one child left, that child is the one to be removed.
- Recursive Case: If the round number kthChild is less than or equal to half the total number of children, then calculates which child will be removed in that round. If kthChild is more than half the total number of children, calls the function itself recursively with half the total number of children and adjusts kthChild accordingly.
Steps to solve this problem:
- Base Case:
- If there's only one child (totalChildren == 1), return 1, as that child is the one to be removed.
- If kthChild is less than or equal to half the total number of children:
- If doubling kthChild exceeds the total number of children, return the remainder of 2 * kthChild divided by the total number of children.
- Otherwise, return 2 * kthChild.
- If kthChild is greater than half the total number of children:
- Recursively calculate the kth child to be removed for half the total number of children and store it in temp.
- If the total number of children is odd, return 2 * temp + 1.
- Otherwise, return 2 * temp - 1.
Code:
Below is the C++ implementation of the above approach:
#include <iostream>
using namespace std;
// Function to calculate the kth child to be removed
long long calculateRemovedChild(long long totalChildren,
long long kthChild)
{
// Base case: if there's only one child left, it's the
// one to be removed
if (totalChildren == 1)
return 1;
// If k is less than or equal to half the total number
// of children
if (kthChild <= (totalChildren + 1) / 2)
{
// If 2*k is greater than the total number of
// children, return the remainder of 2*k divided by
// the total number of children
if (2 * kthChild > totalChildren)
return (2 * kthChild) % totalChildren;
else
// Otherwise, return 2*k
return 2 * kthChild;
}
// Calculate the kth child to be removed for half the
// total number of children
long long temp = calculateRemovedChild(
totalChildren / 2,
kthChild - (totalChildren + 1) / 2);
// If the total number of children is odd, return 2*temp
// + 1
if (totalChildren % 2 == 1)
return 2 * temp + 1;
// Otherwise, return 2*temp - 1
return 2 * temp - 1;
}
int main()
{
long long totalChildren, kthChild;
// Example 1
totalChildren = 7;
kthChild = 1;
cout << calculateRemovedChild(totalChildren, kthChild)
<< "\n";
// Example 2
totalChildren = 7;
kthChild = 3;
cout << calculateRemovedChild(totalChildren, kthChild)
<< "\n";
}
public class RemovedChildCalculator {
// Function to calculate the kth child to be removed
public static long calculateRemovedChild(long totalChildren, long kthChild) {
// Base case: if there's only one child left, it's the one to be removed
if (totalChildren == 1)
return 1;
// If k is less than or equal to half the total number of children
if (kthChild <= (totalChildren + 1) / 2) {
// If 2*k is greater than the total number of children, return the remainder of 2*k divided by the total number of children
if (2 * kthChild > totalChildren)
return (2 * kthChild) % totalChildren;
else
// Otherwise, return 2*k
return 2 * kthChild;
}
// Calculate the kth child to be removed for half the total number of children
long temp = calculateRemovedChild(totalChildren / 2, kthChild - (totalChildren + 1) / 2);
// If the total number of children is odd, return 2*temp + 1
if (totalChildren % 2 == 1)
return 2 * temp + 1;
// Otherwise, return 2*temp - 1
return 2 * temp - 1;
}
public static void main(String[] args) {
long totalChildren, kthChild;
// Example 1
totalChildren = 7;
kthChild = 1;
System.out.println(calculateRemovedChild(totalChildren, kthChild));
// Example 2
totalChildren = 7;
kthChild = 3;
System.out.println(calculateRemovedChild(totalChildren, kthChild));
}
}
// This code is contributed by shivamgupta0987654321
def calculate_removed_child(total_children, kth_child):
# Base case: if there's only one child left, it's the one to be removed
if total_children == 1:
return 1
# If k is less than or equal to half the total number of children
if kth_child <= (total_children + 1) // 2:
# If 2*k is greater than the total number of children,
# return the remainder of 2*k divided by the total number of children
if 2 * kth_child > total_children:
return (2 * kth_child) % total_children
else:
# Otherwise, return 2*k
return 2 * kth_child
# Calculate the kth child to be removed for half the total number of children
temp = calculate_removed_child(total_children // 2, kth_child - (total_children + 1) // 2)
# If the total number of children is odd, return 2*temp + 1
if total_children % 2 == 1:
return 2 * temp + 1
# Otherwise, return 2*temp - 1
return 2 * temp - 1
if __name__ == "__main__":
# Example 1
total_children = 7
kth_child = 1
print(calculate_removed_child(total_children, kth_child))
# Example 2
total_children = 7
kth_child = 3
print(calculate_removed_child(total_children, kth_child))
function calculateRemovedChild(totalChildren, kthChild) {
// Base case: if there's only one child left, it's the one to be removed
if (totalChildren === 1) {
return 1;
}
// If k is less than or equal to half the total number of children
if (kthChild <= Math.floor((totalChildren + 1) / 2)) {
// If 2*k is greater than the total number of children,
// return the remainder of 2*k divided by the total number of children
if (2 * kthChild > totalChildren) {
return (2 * kthChild) % totalChildren;
} else {
// Otherwise, return 2*k
return 2 * kthChild;
}
}
// Calculate the kth child to be removed for half the total number of children
const temp = calculateRemovedChild(Math.floor(totalChildren / 2), kthChild - Math.floor((totalChildren + 1) / 2));
// If the total number of children is odd, return 2*temp + 1
if (totalChildren % 2 === 1) {
return 2 * temp + 1;
}
// Otherwise, return 2*temp - 1
return 2 * temp - 1;
}
// Example 1
let totalChildren = 7;
let kthChild = 1;
console.log(calculateRemovedChild(totalChildren, kthChild));
// Example 2
totalChildren = 7;
kthChild = 3;
console.log(calculateRemovedChild(totalChildren, kthChild));
Output
2 6
Time Complexity: O(log(totalChildren)).
Auxiliary Space: O(log(totalChildren)).