|
2 | 2 |
|
3 | 3 | ## Initial thoughts (stream-of-consciousness)
|
4 | 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 | + |
5 | 15 | ## Refining the problem, round 2 thoughts
|
6 | 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 | + |
7 | 21 | ## Attempted solution(s)
|
| 22 | + |
8 | 23 | ```python
|
9 |
| -class Solution: # paste your code here! |
10 |
| - ... |
| 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] |
11 | 34 | ```
|
| 35 | + |
| 36 | + |
0 commit comments