Facebook Pixel

3178. Find the Child Who Has the Ball After K Seconds

EasyMathSimulation
Leetcode Link

Problem Description

You have n children standing in a line, numbered from 0 to n - 1 from left to right. Initially, child 0 holds a ball.

The ball is passed between children according to these rules:

  • The ball starts moving to the right (from child 0 toward child n - 1)
  • Each second, the child holding the ball passes it to the next child in the current direction
  • When the ball reaches either end of the line (child 0 or child n - 1), the passing direction reverses

Given positive integers n (number of children) and k (number of seconds), determine which child will be holding the ball after exactly k seconds.

For example, with n = 3 children:

  • At second 0: Child 0 has the ball
  • At second 1: Child 1 has the ball (passed right)
  • At second 2: Child 2 has the ball (passed right)
  • At second 3: Child 1 has the ball (direction reversed, passed left)
  • At second 4: Child 0 has the ball (passed left)
  • At second 5: Child 1 has the ball (direction reversed, passed right)

The pattern shows the ball bouncing back and forth between the ends of the line.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

The key insight is recognizing that the ball movement follows a predictable pattern. If we trace the ball's path, we see it moves from position 0 to n-1, then back to 0, creating a repeating cycle.

Let's think about this pattern more carefully. Starting from child 0, the ball takes exactly n-1 passes to reach child n-1. Then it takes another n-1 passes to return to child 0. This means one complete round trip takes 2(n-1) passes.

However, we can simplify this further. Instead of thinking about complete round trips, we can think of the movement as oscillating segments. Each segment consists of n-1 passes where the ball travels from one end to the other. The direction alternates with each segment:

  • Segment 0 (passes 0 to n-2): Ball moves right from child 0 to child n-1
  • Segment 1 (passes n-1 to 2n-3): Ball moves left from child n-1 to child 0
  • Segment 2 (passes 2n-2 to 3n-4): Ball moves right from child 0 to child n-1
  • And so on...

This gives us our approach:

  1. Determine which segment we're in by dividing k by n-1. The quotient tells us the segment number.
  2. Find the position within that segment using k % (n-1). This tells us how many passes have occurred in the current segment.
  3. Check if the segment number is even or odd to determine direction:
    • Even segments (0, 2, 4, ...): moving right, so position is simply the remainder
    • Odd segments (1, 3, 5, ...): moving left, so position is n - 1 - remainder

This mathematical pattern allows us to directly calculate the final position without simulating each individual pass.

Learn more about Math patterns.

Solution Approach

Based on our intuition about the oscillating pattern, we can implement the solution mathematically without simulation.

The implementation breaks down into these steps:

  1. Calculate the segment and position within segment:

    k, mod = divmod(k, n - 1)

    This single line does two things:

    • k (quotient) tells us which segment we're in (0-indexed)
    • mod (remainder) tells us how many passes have occurred within the current segment
  2. Determine the final position based on segment parity:

    return n - mod - 1 if k & 1 else mod
    • We use bitwise AND (k & 1) to check if the segment number is odd or even
    • If k & 1 is 1 (odd segment): The ball is moving left, starting from position n-1. After mod passes to the left, it reaches position n - mod - 1
    • If k & 1 is 0 (even segment): The ball is moving right, starting from position 0. After mod passes to the right, it reaches position mod

Example walkthrough: Let's say n = 4 and k = 5:

  • divmod(5, 3) gives us k = 1 and mod = 2
  • Since k = 1 is odd, the ball is in a leftward segment
  • Starting from position 3 and moving left 2 times: 3 → 2 → 1
  • Formula gives us: n - mod - 1 = 4 - 2 - 1 = 1

The elegance of this solution is that it runs in O(1) time and O(1) space, directly computing the answer without any loops or recursion.

Ready to land your dream job?

Unlock your dream job with a 5-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through a concrete example with n = 5 children and k = 7 seconds.

Step 1: Understand the setup

  • We have 5 children numbered 0, 1, 2, 3, 4
  • The ball starts at child 0
  • We need to find who has the ball after 7 seconds

Step 2: Apply our mathematical approach

First, calculate which segment we're in and our position within it:

k, mod = divmod(7, 5 - 1)  # divmod(7, 4)
# k = 1 (segment number)
# mod = 3 (position within segment)

Step 3: Determine direction based on segment parity

Since k = 1 (odd), we're in a leftward-moving segment.

  • Odd segments mean the ball is traveling from right to left
  • The ball starts this segment at position n - 1 = 4
  • After mod = 3 passes to the left: 4 → 3 → 2 → 1

Using our formula: n - mod - 1 = 5 - 3 - 1 = 1

Step 4: Verify by tracing manually

Let's verify this is correct by simulating each second:

  • Second 0: Child 0 has ball (starting position)
  • Second 1: Child 1 has ball (moving right)
  • Second 2: Child 2 has ball (moving right)
  • Second 3: Child 3 has ball (moving right)
  • Second 4: Child 4 has ball (reached right end, reverse direction)
  • Second 5: Child 3 has ball (moving left)
  • Second 6: Child 2 has ball (moving left)
  • Second 7: Child 1 has ball (moving left) ✓

Our formula correctly predicts child 1 has the ball after 7 seconds!

The key insight is that we divided the movement into segments of length n-1, identified we're in segment 1 (which moves left), and calculated the position directly without simulating all 7 passes.

Solution Implementation

1class Solution:
2    def numberOfChild(self, n: int, k: int) -> int:
3        # Calculate how many complete traversals and remaining steps
4        # Each complete traversal takes (n-1) steps to go from one end to the other
5        complete_traversals, remaining_steps = divmod(k, n - 1)
6      
7        # If complete_traversals is odd, ball is moving right-to-left (backwards)
8        # If complete_traversals is even, ball is moving left-to-right (forwards)
9        if complete_traversals & 1:  # Bitwise AND with 1 checks if odd
10            # Ball is at position (n-1) and moving backwards
11            # Return the position after moving 'remaining_steps' backwards
12            return n - remaining_steps - 1
13        else:
14            # Ball is at position 0 and moving forwards
15            # Return the position after moving 'remaining_steps' forwards
16            return remaining_steps
17
1class Solution {
2    public int numberOfChild(int n, int k) {
3        // Calculate the full cycle length (0 to n-1 and back to 0 is 2*(n-1) steps)
4        // But each half cycle (one direction) takes (n-1) steps
5        int stepsInHalfCycle = n - 1;
6      
7        // Find the position within the current half cycle
8        int positionInHalfCycle = k % stepsInHalfCycle;
9      
10        // Determine which half cycle we're in (even = forward, odd = backward)
11        int halfCycleNumber = k / stepsInHalfCycle;
12      
13        // If we're in an odd-numbered half cycle (going backward from n-1 to 0)
14        if (halfCycleNumber % 2 == 1) {
15            // Calculate position when moving backward
16            return n - 1 - positionInHalfCycle;
17        } else {
18            // If we're in an even-numbered half cycle (going forward from 0 to n-1)
19            // Return the position directly
20            return positionInHalfCycle;
21        }
22    }
23}
24
1class Solution {
2public:
3    int numberOfChild(int n, int k) {
4        // Calculate the position within a single traversal cycle
5        // A complete cycle consists of (n - 1) steps
6        int positionInCycle = k % (n - 1);
7      
8        // Calculate the number of complete cycles
9        // This determines the direction of the current traversal
10        int cycleCount = k / (n - 1);
11      
12        // If cycleCount is odd, we're moving backward (right to left)
13        // If cycleCount is even, we're moving forward (left to right)
14        if (cycleCount % 2 == 1) {
15            // Moving backward: calculate position from the right end
16            return n - positionInCycle - 1;
17        } else {
18            // Moving forward: position is directly the remainder
19            return positionInCycle;
20        }
21    }
22};
23
1/**
2 * Finds the position of a child after k passes in a line game
3 * where children are numbered from 0 to n-1 and a ball is passed
4 * back and forth along the line
5 * 
6 * @param n - The total number of children in the line
7 * @param k - The number of times the ball is passed
8 * @returns The position of the child who has the ball after k passes
9 */
10function numberOfChild(n: number, k: number): number {
11    // Calculate the position within a single cycle (forward and backward)
12    // A complete cycle has (n - 1) * 2 passes, but we only need n - 1 for direction calculation
13    const positionInCycle: number = k % (n - 1);
14  
15    // Determine how many complete half-cycles have occurred
16    // Each half-cycle represents going from one end to the other
17    const halfCycles: number = Math.floor(k / (n - 1));
18  
19    // If odd number of half-cycles, ball is moving backward (right to left)
20    // If even number of half-cycles, ball is moving forward (left to right)
21    if (halfCycles % 2 === 1) {
22        // Ball is moving backward, calculate position from the right end
23        return n - positionInCycle - 1;
24    } else {
25        // Ball is moving forward, position is simply the remainder
26        return positionInCycle;
27    }
28}
29

Time and Space Complexity

The time complexity is O(1) because the algorithm performs a fixed number of operations regardless of the input size. The divmod operation computes both the quotient and remainder in constant time, the bitwise AND operation k & 1 checks if k is odd in constant time, and the conditional return statement with simple arithmetic operations also executes in constant time.

The space complexity is O(1) because the algorithm only uses a constant amount of extra space. It stores two variables k and mod from the divmod operation, and no additional data structures are created that scale with the input size.

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Misunderstanding the Direction After Complete Traversals

A common mistake is incorrectly determining which direction the ball is moving after multiple complete traversals. Developers often confuse:

  • Whether even traversals mean left-to-right or right-to-left
  • The starting position for each new traversal

Incorrect Implementation:

def numberOfChild(self, n: int, k: int) -> int:
    complete_traversals, remaining_steps = divmod(k, n - 1)
  
    # WRONG: Reversed logic for even/odd
    if complete_traversals % 2 == 0:  
        return n - remaining_steps - 1  # This should be for odd traversals
    else:
        return remaining_steps  # This should be for even traversals

Solution: Remember that:

  • Traversal 0 (even): Ball moves from position 0 rightward
  • Traversal 1 (odd): Ball moves from position n-1 leftward
  • The pattern alternates with each complete traversal

2. Off-by-One Error in the Traversal Length

Another frequent error is using n instead of n-1 as the traversal length, forgetting that it takes exactly n-1 steps to go from one end to the other.

Incorrect Implementation:

def numberOfChild(self, n: int, k: int) -> int:
    # WRONG: Using n instead of n-1
    complete_traversals, remaining_steps = divmod(k, n)
  
    if complete_traversals & 1:
        return n - remaining_steps - 1
    else:
        return remaining_steps

Solution: Always use n-1 as the divisor since:

  • From position 0 to position n-1 requires exactly n-1 passes
  • From position n-1 back to position 0 also requires exactly n-1 passes

3. Incorrect Calculation for Leftward Movement

When the ball is moving leftward (odd traversals), calculating the final position can be tricky.

Incorrect Implementation:

def numberOfChild(self, n: int, k: int) -> int:
    complete_traversals, remaining_steps = divmod(k, n - 1)
  
    if complete_traversals & 1:
        # WRONG: Forgetting to subtract 1
        return n - remaining_steps  # This would give positions 1 to n instead of 0 to n-1
    else:
        return remaining_steps

Solution: When moving leftward from position n-1:

  • After 0 steps: position n-1
  • After 1 step: position n-2
  • After mod steps: position n - 1 - mod which simplifies to n - mod - 1

4. Not Handling Edge Cases

Failing to consider boundary conditions like k = 0 or n = 2.

Testing Strategy:

# Always test these cases:
assert numberOfChild(3, 0) == 0  # No movement
assert numberOfChild(2, 1) == 1  # Minimal n value
assert numberOfChild(2, 2) == 0  # Ball returns to start
assert numberOfChild(5, 4) == 4  # Exact traversal boundary

Solution: The mathematical formula naturally handles these edge cases, but it's crucial to verify them during development and testing.

Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

Which two pointer techniques do you use to check if a string is a palindrome?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More