Skip to content

Commit bdf10fc

Browse files
authored
Merge pull request #849 from dusunax/main
[SunaDu] Week 5
2 parents cd99cbf + 42c3949 commit bdf10fc

File tree

5 files changed

+210
-0
lines changed

5 files changed

+210
-0
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
'''
2+
# 121. Best Time to Buy and Sell Stock
3+
4+
use **bottom-up dynamic programming** to solve the problem.
5+
6+
## Time and Space Complexity
7+
```
8+
TC: O(n)
9+
SC: O(1)
10+
```
11+
12+
## TC is O(n):
13+
- iterating through the list just once to find the maximum profit. = O(n)
14+
15+
## SC is O(1):
16+
- using two variables to store the minimum price and maximum profit. = O(1)
17+
'''
18+
class Solution:
19+
def maxProfit(self, prices: List[int]) -> int:
20+
if len(prices) == 1:
21+
return 0
22+
23+
lowest_price = prices[0] # SC: O(1)
24+
max_profit = 0 # SC: O(1)
25+
26+
for price in prices: # TC: O(n)
27+
lowest_price = min(price, lowest_price)
28+
curr_profit = price - lowest_price
29+
max_profit = max(curr_profit, max_profit)
30+
31+
return max_profit

encode-and-decode-strings/dusunax.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
'''
2+
# 271. Encode and Decode Strings
3+
4+
## Time and Space Complexity
5+
6+
Use ":" as a separator and also store the length of each string to decode the string correctly.
7+
8+
9+
### encode
10+
11+
```
12+
TC: O(n * k)
13+
SC: O(m)
14+
```
15+
16+
#### TC is O(n * k):
17+
18+
- iterating through the list of strings and appending each string to the result. = O(n * k)
19+
- f-string is O(k)
20+
21+
#### SC is O(m):
22+
- storing the result in a string.
23+
24+
### decode
25+
26+
```
27+
TC: O(m)
28+
SC: O(m)
29+
```
30+
31+
#### TC is O(m):
32+
- iterating over the string until the string length is 0. = O(m)
33+
- do list slicings for extract parts and removing the processed section = each operation takes O(k)
34+
35+
#### SC is O(m):
36+
- storing the result in a list(total length of strings is m) = O(m)
37+
38+
'''
39+
40+
class Solution:
41+
"""
42+
@param: strs: a list of strings
43+
@return: encodes a list of strings to a single string.
44+
"""
45+
def encode(self, strs):
46+
result = ''
47+
for str in strs: # TC: O(n)
48+
result += f"{len(str)}:{str}" # TC: O(k)
49+
return result
50+
51+
"""
52+
@param: str: A string
53+
@return: decodes a single string to a list of strings
54+
"""
55+
def decode(self, str):
56+
result = []
57+
58+
while len(str) > 0: # TC: O(m)
59+
length = int(str[:1]) # TC: O(k)
60+
string = str[2:length+2] # TC: O(k)
61+
str = str[length+2:] # TC: O(k)
62+
63+
result.append(string) # SC: O(m)
64+
65+
return result

group-anagrams/dusunax.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
'''
2+
# 49. Group Anagrams
3+
4+
use **hash map** to solve the problem.
5+
6+
## Time and Space Complexity
7+
```
8+
TC: O(N * K * Log(K))
9+
SC: O(N * K)
10+
```
11+
12+
## TC is O(N * K * Log(K)):
13+
- iterating through the list of strings and sorting each string. = O(N * K * Log(K))
14+
15+
## SC is O(N * K):
16+
- using a hash map to store the sorted strings. = O(N * K)
17+
'''
18+
class Solution:
19+
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
20+
result = defaultdict(list)
21+
22+
for str in strs: # TC: O(N)
23+
sorted_key = ''.join(sorted(str)) # sorting 👉 TC: O(K * Log(K))
24+
result[sorted_key].append(str) # TC: O(1) on average
25+
26+
return list(result.values())
27+

implement-trie-prefix-tree/dusunax.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
'''
2+
# 208. Implement Trie (Prefix Tree)
3+
4+
```
5+
- Node structure
6+
{children: {char: {children: { ... }, is_end: False}}, is_end: False}
7+
```
8+
9+
## Time and Space Complexity
10+
11+
```
12+
TC: O(n)
13+
SC: O(n)
14+
```
15+
16+
#### TC is O(n):
17+
- insert, search, startsWith: iterating through the word just once. = O(n)
18+
19+
#### SC is O(n):
20+
- insert, search, startsWith: using a hash map to store the children nodes. = O(n)
21+
'''
22+
23+
class Trie:
24+
def __init__(self):
25+
self.root = {"children": {}, "is_end": False}
26+
27+
def insert(self, word: str) -> None:
28+
node = self.root
29+
for char in word:
30+
if char not in node["children"]:
31+
node["children"][char] = {"children": {}, "is_end": False}
32+
node = node["children"][char]
33+
node["is_end"] = True
34+
35+
def search(self, word: str) -> bool:
36+
node = self.root
37+
for char in word:
38+
if char not in node["children"]:
39+
return False
40+
node = node["children"][char]
41+
return node["is_end"]
42+
43+
def startsWith(self, prefix: str) -> bool:
44+
node = self.root
45+
for char in prefix:
46+
if char not in node["children"]:
47+
return False
48+
node = node["children"][char]
49+
return True

word-break/dusunax.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
'''
2+
# 139. Word Break
3+
4+
use dynamic programming to check if the string is segmentable.
5+
6+
> **use dp to avoid redundant computations:**
7+
> backtracking approach will check all possible combinations of words recursively, which has time complexity of O(2^n))
8+
9+
## Time and Space Complexity
10+
11+
```
12+
TC: O(n^2)
13+
SC: O(n)
14+
```
15+
16+
#### TC is O(n^2):
17+
- nested loops for checking if the string is segmentable. = O(n^2)
18+
- outer loop: iterate each char index from the start to the end. = O(n)
19+
- inner loop: for each index in the outer loop, checks substrings within the range of valid words in wordDict. = worst case, O(n)
20+
21+
#### SC is O(n):
22+
- using a dp array to store whether index i is segmentable. = O(n)
23+
'''
24+
class Solution:
25+
def wordBreak(self, s: str, wordDict: List[str]) -> bool:
26+
word_set = set(wordDict)
27+
n = len(s)
28+
29+
segment_dp = [False] * (n + 1) # SC: O(n)
30+
segment_dp[0] = True # Base case: an empty string is segmentable
31+
32+
for end in range(1, n + 1): # TC: O(n^2)
33+
for start in range(end):
34+
if segment_dp[start] and s[start:end] in word_set:
35+
segment_dp[end] = True
36+
break
37+
38+
return segment_dp[n]

0 commit comments

Comments
 (0)