Skip to content

Commit 0049e2f

Browse files
My solution for 664
1 parent 1772dca commit 0049e2f

File tree

1 file changed

+113
-2
lines changed

1 file changed

+113
-2
lines changed

problems/664/jeremymanning.md

+113-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,122 @@
11
# [Problem 664: Strange Printer](https://leetcode.com/problems/strange-printer/description/?envType=daily-question)
22

33
## Initial thoughts (stream-of-consciousness)
4+
- Ugh, *another* dynamic programming problem!? I hope this sequence ends soon 😱
5+
- Ok, so how can we solve this one... 🤔
6+
- First we can do some housekeeping by removing any repeated characters. This will take $O(n)$ time, which is "free" since the full algorithm will almost certainly by slower than that:
7+
```python
8+
def simplify(s):
9+
x = s[0]
10+
for c in s[1:]:
11+
if c != x[-1]:
12+
x += c
13+
return x
14+
```
15+
- Next, we should define a helper function:
16+
- Take in...what? Maybe a start index and end index for a substring of the (simplified) `s`? We could also pass in a substring directly, but that'd require copying the substrings in memory (inefficient). Since nothing will get modified, I think we can just reference using indices.
17+
- The helper function should return the turns required for that substring
18+
- To figure out: how will this work?
19+
- Then the function will be something like
20+
```python
21+
s = simplify(s)
22+
return helper(0, len(s) - 1)
23+
```
24+
- I'm guessing `helper` will end up calling the same indices multiple times recursively, so we should also cache the results to avoid re-computing them:
25+
```python
26+
cache = {}
27+
def helper(a, b):
28+
if (a, b) in cache:
29+
return cache[(a, b)]
30+
31+
turns = <do computations, probably call helper recursively>
32+
cache[(a, b)] = turns
33+
return turns
34+
```
35+
- So the "trick" here will be figuring out how that `helper` function should look.
436

537
## Refining the problem, round 2 thoughts
38+
- If the substring is empty, return 0. This happens if `a > b`.
39+
- If the substring is just a single character, return 1 (`a == b`)
40+
- We'll need to iteratively improve on the number of turns. The worst case would be `b - a + 1` (i.e., one turn per character).
41+
- If there are duplicated characters (since we've already simplified, these will be separated by intervening characters), we can improve on this worst case. So we'll need to detect duplicates.
42+
- We could start at the first character, and see if there are any duplicates of *that* character. If we find a duplicate (say the first one occurs at position `j`) then we can save one turn (print the duplicate character, then figure out how many turns are needed for `s[a + 1:j]`. So the total for that sub-sequence would be `1 + helper(a, j - 1)`. Then we can skip over character `j`. Then we need to compute the number of turns needed for `s[j + 1:b]`. We can update `min_turns = min(min_turns, helper(a, j - 1) + helper(j + 1, b))`
43+
- If we find *another* duplicate later on in the sequence, we can just repeat this process. But the cache will avoid re-computing things many times.
44+
- Let's try this...it might not be too bad. I might be missing something, but I'm surprised this is a "hard" problem; the recent "medium" problems have seemed trickier!
645

746
## Attempted solution(s)
847
```python
9-
class Solution: # paste your code here!
10-
...
48+
class Solution:
49+
def strangePrinter(self, s: str) -> int:
50+
def simplify(s):
51+
x = s[0]
52+
for c in s[1:]:
53+
if c != x[-1]:
54+
x += c
55+
return x
56+
57+
s = simplify(s)
58+
cache = {}
59+
def helper(a, b):
60+
if a > b:
61+
return 0
62+
elif a == b:
63+
return 1
64+
elif (a, b) in cache:
65+
return cache[(a, b)]
66+
67+
min_turns = b - a + 1
68+
for i in range(a + 1, b + 1):
69+
if s[a] == s[i]:
70+
min_turns = min(min_turns, helper(a, i - 1) + helper(i + 1, b))
71+
cache[(a, b)] = min_turns
72+
return min_turns
73+
74+
return helper(0, len(s) - 1)
1175
```
76+
- Given test cases pass
77+
- Let's try some longer strings:
78+
- `s = "abaabababaabababababbbabababacccbbcbcbabaababa"`: pass(!!)
79+
- `s = "ddzdmpdnrmndphslxhewdhrnwlmlinkpttuopysqgvhssxqxiozhffyxwvyfcwhkpxxcmxzxvodtjsiiuzzmxveddcvtuhxanzgb": womp womp...fail 😞
80+
- Ok...let's brainstorm...I think there are a few possible things that could be happening:
81+
- Most likely: the logic of just checking for the first matching character might not make sense. How do we match other characters?
82+
- Actually, maybe we should initialize `min_turns` to `1 + helper(a + 1, b)`. That way each recursive call will consider matches of the "new `a`" in turn. I wonder if that will just fix the problem "for free."
83+
```python
84+
class Solution:
85+
def strangePrinter(self, s: str) -> int:
86+
def simplify(s):
87+
x = s[0]
88+
for c in s[1:]:
89+
if c != x[-1]:
90+
x += c
91+
return x
92+
93+
s = simplify(s)
94+
cache = {}
95+
def helper(a, b):
96+
if a > b:
97+
return 0
98+
elif a == b:
99+
return 1
100+
elif (a, b) in cache:
101+
return cache[(a, b)]
102+
103+
min_turns = 1 + helper(a + 1, b)
104+
for i in range(a + 1, b + 1):
105+
if s[a] == s[i]:
106+
min_turns = min(min_turns, helper(a, i - 1) + helper(i + 1, b))
107+
cache[(a, b)] = min_turns
108+
return min_turns
109+
110+
return helper(0, len(s) - 1)
111+
```
112+
- That fixes the above test cases! Let's try some more...
113+
- `s = "niqmxxbwvonppouiypidwbqmodqvtnlaxxdgpayhmzywnyojfkqobatdyhfkzayazifwqyfpgxlpbupyascdfnqtnmrdlwwkagiq": pass
114+
- `s = "naajdcjcrvbhmjxgkenbqdkikmnxufughnjwasclwuvrenhksnosyigmnovmexmegklcqllfmxbbhtvazzcqhltoiukvsvgnwyvl": pass
115+
- What about some silly cases?
116+
- `s = "aaaaaaaaaaa": pass
117+
- Ok, let's try submitting...
118+
119+
![Screenshot 2024-08-20 at 11 12 39 PM](https://github.com/user-attachments/assets/281bcbb9-80ea-419e-bf2c-727c81ab59b7)
120+
121+
Solved!
122+

0 commit comments

Comments
 (0)