|
| 1 | +# [Problem 1823: Find the Winner of the Circular Game](https://leetcode.com/problems/find-the-winner-of-the-circular-game/description/?envType=daily-question) |
| 2 | + |
| 3 | +## Initial thoughts (stream-of-consciousness) |
| 4 | + |
| 5 | +- pretty sure there's going to be an analytic solution that runs in $O(1)$ time & space for this, but it's not immediately obvious to me what it is... |
| 6 | +- interesting that the constraints say `k` will never be larger than `n`, I wonder if that's significant... |
| 7 | +- going to try to brute-force this first and see if I can find a pattern in the output |
| 8 | +- could do something involving `itertools.cycle` again, but that's probably going to be inefficient since the iterable (remaining players) will change each round |
| 9 | +- I think I'll need to keep track of my current index in the players circle (list) and increment/update it each round. That way if I `pop` the `i`th player from the list, `i` will immediately refer to the player to the right (clockwise) of the removed player, which is who I want to start with next round. |
| 10 | +- I think I need to use modulo to deal with the wrap-around... how will that help... |
| 11 | +- ah, instead of starting to count from the player at the current index `i`, I can start from the 1st player, add my current offset `i` from the start of the players list, and then mod *that* by the current length of the list to get my new player index to remove. |
| 12 | +- Since we cound the 1st player as 1, 2nd player as 2, etc., I'll need to subtract 1 from the index I want to remove |
| 13 | + |
| 14 | + |
| 15 | +## Refining the problem, round 2 thoughts |
| 16 | + |
| 17 | +- How might we go about solving this in constant time... |
| 18 | +- I don't see a clear pattern in the output when holding `n` or `k` constant and incrementing the other... maybe it's related to the cumulative sum of the player positions? |
| 19 | +- thought through this for a while, broke down and decided to google it. Turns out this is the [Josephus problem](https://en.wikipedia.org/wiki/Josephus_problem) and there isn't a constant-time solution for the general case. There *is* an $O(k \mathrm{log} n)$ solution that involves recursion and memoization, but for the sake of time I'm going to be satisfied with my $O(n)$ version. |
| 20 | + |
| 21 | +## Attempted solution(s) |
| 22 | + |
| 23 | +```python |
| 24 | +class Solution: |
| 25 | + def findTheWinner(self, n: int, k: int) -> int: |
| 26 | + players = list(range(1, n+1)) |
| 27 | + ix_to_remove = 0 |
| 28 | + |
| 29 | + while len(players) > 1: |
| 30 | + ix_to_remove = (ix_to_remove + k - 1) % len(players) |
| 31 | + players.pop(ix_to_remove) |
| 32 | + |
| 33 | + return players[0] |
| 34 | +``` |
| 35 | + |
| 36 | + |
0 commit comments