|
1 | 1 | # [Problem 650: 2 Keys Keyboard](https://leetcode.com/problems/2-keys-keyboard/description/?envType=daily-question)
|
2 | 2 |
|
3 | 3 | ## Initial thoughts (stream-of-consciousness)
|
| 4 | +- If `n` is a power of 2 (1, 2, 4, 8, etc.) then we can return `log2(n)` |
| 5 | +- If `n` is a power of `x` then we can return `logx(n)` |
| 6 | +- If `n` is *not* an integer power of anything, then we might just need to copy the first 'A' and then paste it `n` times...although...maybe there's a faster way? |
| 7 | +- Maybe there's a dynamic programming solution: if `n` is divisible by some integer `x`, then: |
| 8 | + - First get `x` As |
| 9 | + - Then copy |
| 10 | + - Then paste `n // x` times |
| 11 | +- So maybe we can build up iteratively: |
| 12 | + - If `n` is 1, then the number of steps is 0 |
| 13 | + - If `n` is 2: copy + paste |
| 14 | + - If `n` is 3: copy + paste + paste |
| 15 | + - If `n` is 4: solve for 2 (2 steps), then copy + paste |
| 16 | + - If `n` is 5: copy + paste + paste + paste + paste |
| 17 | + - If `n` is 6: min(solve for 3 (3 steps), then copy + paste, solve for 2 (2 steps), then copy + paste + paste) |
| 18 | + - And so on... |
| 19 | +- If `n` is prime, we just need to copy and then paste `n - 1` times |
| 20 | +- If `n` is divisible by some integer `x`, then (as listed above) we first compute the number of steps required to get `x` As, then copy, then paste `n // x` times |
| 21 | + - We'll have to compute the minimum over all possible `x`s (i.e., factors of `n`) |
| 22 | + - Suppose we're up to `i` As. Do we need to check all the way to `i`? I think we just need to check up to `sqrt(i)`-- e.g., if `i` is 12 then we can factorize `i` into (1, 12), (2, 6), or (3, 4). In general, if we can factorize `i` to the product of `x` and `y`, then either `x` or `y` must be less than or equal to `sqrt(i)`. (At most, `x == y == sqrt(i)`.) |
| 23 | + - The number of steps needed to get `i` As (where `x` and `y` are factors) is `min(i, steps[x - 1] + (i // x), steps[y - 1] + (i // y))`. But then we need to potentially update this (to a new minimum) for any other factors that require fewer steps. |
4 | 24 |
|
5 | 25 | ## Refining the problem, round 2 thoughts
|
| 26 | +- We just need to initialize an array to store the number of steps needed to get to each number of As, up to `n`. We can skip `n <= 1`, since we know that requires 0 steps. |
| 27 | +- Then we just loop through `i in range(2, n + 1)` and: |
| 28 | + - Set `steps[i - 1] = i` |
| 29 | + - For `j in range(2, int(math.sqrt(i)) + 1)`: |
| 30 | + - `if i % j == 0:` |
| 31 | + - `steps[i - 2] = min(steps[i - 1], steps[j - 1] + (i // j), steps[i // j - 1] + j)` |
| 32 | +- Then return `steps[n - 1]` |
| 33 | +- Let's try this... |
6 | 34 |
|
7 | 35 | ## Attempted solution(s)
|
8 | 36 | ```python
|
9 |
| -class Solution: # paste your code here! |
10 |
| - ... |
| 37 | +import math |
| 38 | + |
| 39 | +class Solution: |
| 40 | + def minSteps(self, n: int) -> int: |
| 41 | + if n <= 1: |
| 42 | + return 0 |
| 43 | + steps = [0] * n |
| 44 | + |
| 45 | + for i in range(2, n + 1): |
| 46 | + steps[i - 1] = i |
| 47 | + for j in range(2, int(math.sqrt(i)) + 1): |
| 48 | + if i % j == 0: |
| 49 | + steps[i - 1] = min(steps[i - 1], steps[j - 1] + (i // j), steps[i // j - 1] + j) |
| 50 | + |
| 51 | + return steps[n - 1] |
11 | 52 | ```
|
| 53 | +- Given test cases pass |
| 54 | +- More tests: |
| 55 | + - `n = 1000`: pass |
| 56 | + - `n = 500`: pass |
| 57 | + - `n = 64`: pass |
| 58 | + - `n = 999`: pass |
| 59 | +- Ok...seems good; submitting... |
| 60 | + |
| 61 | + |
| 62 | + |
| 63 | +Solved! |
| 64 | + |
0 commit comments