HomeLeetcode390. Elimination Game - Leetcode Solutions

390. Elimination Game – Leetcode Solutions

Description

You have a list arr of all integers in the range [1, n] sorted in a strictly increasing order. Apply the following algorithm on arr:

  • Starting from left to right, remove the first number and every other number afterward until you reach the end of the list.
  • Repeat the previous step again, but this time from right to left, remove the rightmost number and every other number from the remaining numbers.
  • Keep repeating the steps again, alternating left to right and right to left, until a single number remains.

Given the integer n, return the last number that remains in arr.

Examples:

Example 1:

Input: n = 9
Output: 6
Explanation:
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
arr = [2, 4, 6, 8]
arr = [2, 6]
arr = [6]

Example 2:

Input: n = 1
Output: 1

Solution in Python

Key Observations:

  1. Alternating Elimination Direction:
    • Each round of elimination alternates between left-to-right and right-to-left.
    • Starting from the left, we eliminate the first element and every other element. This effectively doubles the step size (spacing between numbers).
    • When going from right-to-left, the elimination pattern is the same (every other element), but starts from the end.
  2. Updating Key Variables:
    • Head: The first remaining element in the list.
    • Step: The interval or spacing between numbers in the current sequence after each elimination.
    • Direction: Left-to-right or right-to-left.
    • Remaining Count: How many elements remain in the current iteration.
  3. Impact of Each Round on Variables:
    • Left-to-right: Always moves the head to the next element (head += step), as the first element is always removed.
    • Right-to-left: Moves the head to the next element only if there’s an odd number of remaining elements (since the last element is removed).
    • Doubling the Step: Each round effectively doubles the step because we eliminate every other element.
  4. Termination:
    • The process terminates when only one element remains.
Python
class Solution:
    def lastRemaining(self, n: int) -> int:
        # Initialize variables
        head = 1          # Starting element
        step = 1          # Initial step size
        left_to_right = True  # Start elimination from left-to-right
        remaining = n     # Number of elements remaining

        # Loop until only one element remains
        while remaining > 1:
            # If we're moving left-to-right, or if there is an odd number of remaining elements
            # (in right-to-left, odd remaining means the head will shift)
            if left_to_right or remaining % 2 == 1:
                head += step
            
            # Double the step for the next round as every other element is removed
            step *= 2
            # Toggle the direction
            left_to_right = not left_to_right
            # Halve the remaining elements as half are removed in each round
            remaining //= 2

        # The last remaining number is stored in head
        return head

Explanation of the Code

  1. Initialize Variables:
    • head is set to 1 because the list starts at 1.
    • step starts at 1, representing the initial spacing between numbers.
    • left_to_right is True, as we begin eliminating from left to right.
    • remaining is initialized to n, representing the count of elements initially.
  2. Loop Execution:
    • The loop continues until only one element remains (remaining > 1).
    • If we are eliminating left-to-right, or if the number of elements is odd when eliminating right-to-left, we update the head (head += step).
    • We double the step after each round (step *= 2) to reflect the increasing gap between numbers.
    • We toggle the direction (left_to_right = not left_to_right) to alternate between left-to-right and right-to-left eliminations.
    • The remaining count is halved each time because half of the elements are removed in each round.
  3. Return the Last Remaining Number:
    • When the loop finishes, head will contain the last remaining element.

Solution in C++

C++
class Solution {
public:
    int lastRemaining(int n) {
        // Initialize variables:
        // - 'left_to_right' indicates the current direction of elimination.
        // - 'remaining' keeps track of the number of elements still in the list.
        // - 'step' is the interval between remaining elements after each round.
        // - 'head' keeps track of the starting element in the list after each round.
        bool left_to_right = true;
        int remaining = n;
        int step = 1;
        int head = 1;
        
        // Loop until only one element remains
        while (remaining > 1) {
            // If we are moving left to right or if remaining elements are odd,
            // the head will move forward by 'step' amount.
            if (left_to_right || remaining % 2 == 1) {
                head += step;
            }
            
            // After each round, the number of remaining elements is halved,
            // and the step size doubles.
            remaining /= 2;
            step *= 2;
            left_to_right = !left_to_right;  // Alternate direction
        }
        
        // The last remaining element is stored in 'head'
        return head;
    }
};

Solution in Javascript

JavaScript
var lastRemaining = function(n) {
    // Initialize the first number in the sequence
    let first = 1;
    
    // Initialize the step size, which doubles every round
    let step = 1;
    
    // Track whether we are moving left to right (true) or right to left (false)
    let leftToRight = true;
    
    // Continue until there is only one element remaining
    while (n > 1) {
        // If moving left to right or if n is odd, update `first`
        if (leftToRight || n % 2 === 1) {
            first += step;
        }
        
        // Move to the next round with a doubled step and switch direction
        step *= 2;
        n = Math.floor(n / 2);
        leftToRight = !leftToRight;
    }
    
    // `first` will hold the last remaining number
    return first;
};

Solution in Java

Java
class Solution {
    public int lastRemaining(int n) {
        // Initialize variables for the first element, step size, and number of elements left
        int start = 1;       // Start of the list in each iteration
        int step = 1;        // Step size between elements after each round
        int remaining = n;   // Number of remaining elements in the list
        boolean leftToRight = true; // Direction flag, starts with left-to-right pass

        // Continue the elimination until only one element remains
        while (remaining > 1) {
            // If we're moving from left-to-right, or if the remaining count is odd when moving right-to-left,
            // we must update the starting element because the first element is always removed.
            if (leftToRight || remaining % 2 == 1) {
                start += step;
            }

            // Update remaining number of elements and step size
            remaining /= 2;
            step *= 2;

            // Toggle the direction for the next pass
            leftToRight = !leftToRight;
        }

        // 'start' is the last remaining element
        return start;
    }
}

Subscribe
Notify of

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments

Popular