Skip to content

Commit

Permalink
Merge pull request #472 from haklee/main
Browse files Browse the repository at this point in the history
[haklee] week 6
  • Loading branch information
haklee authored Sep 21, 2024
2 parents 5e24497 + 5e09250 commit ddd3676
Show file tree
Hide file tree
Showing 4 changed files with 283 additions and 0 deletions.
105 changes: 105 additions & 0 deletions container-with-most-water/haklee.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
"""TC: O(n), SC: O(1)
아이디어:
높이 리슀트 l이 μ£Όμ–΄μ‘Œλ‹€κ³  ν•˜μž. 그리고 이 μ•ˆμ— μžˆλŠ” μ΅œλŒ€ 수쑰 면적을 f(l)이라고 ν•˜μž.
β–‘ β–‘ β–‘
β–‘ β–‘ β–‘ β–‘
β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘
β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘
β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘
2,5,3,3,1,3,1,2,2,5,3,5,3,4
^
l
그러면 λ‹€μŒμ΄ 항상 μ„±λ¦½ν•œλ‹€.
- l의 μ–‘ 끝의 κ°’ 쀑 μž‘μ€ κ°’ xκ°€ μ•žμͺ½μ— μžˆμ—ˆλ‹€κ³  ν•΄λ³΄μž. xλ₯Ό λΊ€ 리슀트 l`을 λ§Œλ“ λ‹€.
- μ΄λ•Œ μž‘μ€ 값이 λ’·μͺ½μ— μžˆμ—ˆμ–΄λ„ μΌλ°˜μ„±μ„ μžƒμ§€ μ•ŠλŠ”λ‹€.
β”‚β–‘ β–‘ β–‘
β”‚β–‘ β–‘ β–‘ β–‘
β”‚β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘
β–‘β”‚β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘
β–‘β”‚β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘
2β”‚5,3,3,1,3,1,2,2,5,3,5,3,4
^ ^
x l`
- f(l)은 κ·Έλ ‡λ‹€λ©΄
- f(l`)μ΄κ±°λ‚˜(즉, xλ₯Ό 쓰지 μ•Šμ•˜κ±°λ‚˜)
- xλ₯Ό μ¨μ„œ λ§Œλ“  수쑰 면적 쀑에 μžˆλ‹€.
- 그런데 xλŠ” l의 μ–‘ 끝 κ°’ 쀑에 μž‘μ€ κ°’μ΄λ―€λ‘œ, μ•„λž˜μ™€ 같은 뢄석을 ν•  수 μžˆλ‹€.
1) xλ₯Ό μ¨μ„œ λ§Œλ“œλŠ” 수쑰의 λ†’μ΄λŠ” 아무리 높아도 xλ‹€. x보닀 μž‘μ•„μ§ˆ μˆ˜λŠ” μžˆμ–΄λ„, x보닀 컀질 μˆ˜λŠ” μ—†λ‹€.
2) xλ₯Ό μ¨μ„œ λ§Œλ“œλŠ” 수쑰의 폭은 l의 λ‹€λ₯Έμͺ½ 끝에 μžˆλŠ” 높이λ₯Ό μ„ νƒν–ˆμ„λ•Œ μ΅œλŒ€κ°€ λœλ‹€.
- κ·ΈλŸ¬λ―€λ‘œ, xλ₯Ό μ¨μ„œ λ§Œλ“€ 수 μžˆλŠ” 수쑰의 μ΅œλŒ€ ν¬κΈ°λŠ” l의 λ‹€λ₯Έμͺ½ 끝에 μžˆλŠ” 높이λ₯Ό μ„ νƒν•œ 경우 λ‚˜μ˜¨λ‹€.
μœ„μ˜ λ‚΄μš©μ„ μ•„λž˜μ˜ μ„€λͺ…을 톡해 μ‹œκ°μ μœΌλ‘œ 확인할 수 μžˆλ‹€.
- μ–‘ 끝을 μ„ νƒν•œ 경우 x둜 λ§Œλ“€ 수 μžˆλŠ” μ΅œλŒ€ 면적이닀.
β”‚β–‘ β–‘ β–‘
β”‚β–‘ β–‘ β–‘ β–‘
β”‚β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘
β– β”‚β–  β–  β–  β–  β–  β–  β–  β–  β–  β–  β–  β–  β– 
β– β”‚β–  β–  β–  β–  β–  β–  β–  β–  β–  β–  β–  β–  β– 
2β”‚5,3,3,1,3,1,2,2,5,3,5,3,4
^ ^
- xλŠ” κ·ΈλŒ€λ‘œ λ‘” 채 λ‹€λ₯Έμͺ½ 끝을 μ•ˆμͺ½μœΌλ‘œ 더 μ΄λ™ν•˜λ©΄ 수쑰 λ†’μ΄λŠ” λ™μΌν•œλ° 폭은 더 μž‘μ•„μ§„λ‹€.
β”‚β–‘ β–‘ β–‘
β”‚β–‘ β–‘ β–‘ β–‘
β”‚β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘
β– β”‚β–  β–  β–  β–  β–  β–  β–  β–  β–  β–  β–  β–‘ β–‘
β– β”‚β–  β–  β–  β–  β–  β–  β–  β–  β–  β–  β–  β–‘ β–‘
2β”‚5,3,3,1,3,1,2,2,5,3,5,3,4
^ ^
- 심지어 x보닀 μž‘μ€ 높이 값을 μ„ νƒν•œ 경우 수쑰 높이도 μž‘μ•„μ§€κ³  폭도 μž‘μ•„μ§€λŠ” 일이 μΌμ–΄λ‚œλ‹€.
β”‚β–‘ β–‘ β–‘
β”‚β–‘ β–‘ β–‘ β–‘
β”‚β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘
β–‘β”‚β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘
β– β”‚β–  β–  β–  β–  β–  β–  β–‘ β–‘ β–‘ β–‘ β–‘ β–‘ β–‘
2β”‚5,3,3,1,3,1,2,2,5,3,5,3,4
즉, μœ„μ˜ λ‚΄μš©μ„ μ’…ν•©ν•˜λ©΄ λ‹€μŒμ„ 확인할 수 μžˆλ‹€.
- f(l) = max( (l의 μ–‘ 끝 높이λ₯Ό μ„ νƒν•΄μ„œ λ§Œλ“  수쑰 넓이), f(l`) )
- 그런데 f(l`)도 f(l)을 κ΅¬ν•œ 것과 같은 λ°©μ‹μœΌλ‘œ ꡬ할 수 μžˆλ‹€. 즉, μƒˆλ‘œ λ§Œλ“€μ–΄μ§„ l`의 μ–‘ 끝 높이 쀑
짧은 μͺ½μ„ λΊ€ 리슀트 l``을 λ§Œλ“€μ–΄μ„œ μœ„μ˜ 과정을 λ°˜λ³΅ν•  수 μžˆλ‹€.
- 즉, f(l)은 μ•„λž˜μ˜ 과정을 λ°˜λ³΅ν•˜μ—¬ ꡬ할 수 μžˆλ‹€.
- l의 μ–‘ 끝 높이λ₯Ό μ¨μ„œ 수쑰 넓이λ₯Ό κ΅¬ν•˜κ³ , κΈ°μ‘΄ μ΅œλŒ€ 넓이와 λΉ„κ΅ν•˜μ—¬ 더 큰 값을 μ΅œλŒ€ 넓이에 λŒ€μž…ν•œλ‹€.
- lμ—μ„œ 짧은 μͺ½ 높이λ₯Ό λΊ€λ‹€.
- μœ„ 과정을 l에 μ•„μ΄ν…œμ΄ ν•˜λ‚˜λ§Œ 남을 λ•ŒκΉŒμ§€ 반볡.
SC:
- 투 포인터λ₯Ό μ¨μ„œ l의 μ‹œμž‘, 끝 인덱슀λ₯Ό κ΄€λ¦¬ν•˜λ©΄ O(1).
- 수쑰 μ΅œλŒ€ 넓이값 관리, O(1).
- μ’…ν•©ν•˜λ©΄ O(1).
TC:
- 리슀트의 μ–‘ 끝 높이λ₯Ό 톡해 면적 κ΅¬ν•˜κΈ°, O(1).
- 포인터 이동 O(1).
- 포인터 μ΄λ™μ‹œ 두 포인터 μ‚¬μ΄μ˜ 거리가 1μ”© 항상 κ°μ†Œν•˜λ―€λ‘œ μœ„ 과정을 μ΅œλŒ€ n-2번 반볡.
- μ’…ν•©ν•˜λ©΄ O(n).
"""


class Solution:
def maxArea(self, height: List[int]) -> int:
max_area = -1
s, e = 0, len(height) - 1
while s < e:
max_area = max(max_area, (e - s) * min(height[s], height[e]))
if height[s] > height[e]:
e -= 1
else:
s += 1
return max_area
59 changes: 59 additions & 0 deletions design-add-and-search-words-data-structure/haklee.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
"""searchμ‹œ: TC: O(n), SC: O(n)
word의 max lengthκ°€ w, `addWord`λ₯Ό 톡해 λ§Œλ“€μ–΄μ§„ λ…Έλ“œ κ°œμˆ˜κ°€ n개라고 ν•˜μž.
아이디어:
`implement-trie-prefix-tree` λ¬Έμ œμ—μ„œ κ΅¬ν˜„ν•œ trieμ—μ„œ search λΆ€λΆ„λ§Œ recursiveν•œ dfs κ΅¬ν˜„μœΌλ‘œ μˆ˜μ •.
SC:
- trie의 λ…Έλ“œ 개수 O(n).
- dfsμ‹œ μŠ€νƒ κΉŠμ΄λŠ” μ΅œλŒ€ w. 즉, O(w). 그런데 μŠ€νƒ κΉŠμ΄λŠ” λ…Έλ“œ κ°œμˆ˜λ³΄λ‹€ 클 수 μ—†λ‹€. 즉, O(w) < O(n).
- μ’…ν•©ν•˜λ©΄, O(n) + O(w) < O(n) + O(n) = O(n).
TC:
- μ΅œμ•…μ˜ 경우 λͺ¨λ“  λ…Έλ“œ 순회. O(n).
"""


class WordDictionary:

def __init__(self):
self.next: dict[str, WordDictionary] = {}
self.end: bool = False

def addWord(self, word: str) -> None:
cur = self

for c in word:
cur.next[c] = cur.next.get(c, WordDictionary())
cur = cur.next[c]

cur.end = True

def search(self, word: str) -> bool:
cur = self

return self._search(cur, word, 0)

def _search(self, trie, word: str, ind: int) -> bool:
if ind == len(word):
return trie.end

c = word[ind]

if c == ".":
return any(
[self._search(node, word, ind + 1) for node in trie.next.values()]
)

if c not in trie.next:
return False

return self._search(trie.next[c], word, ind + 1)


# Your WordDictionary object will be instantiated and called as such:
# obj = WordDictionary()
# obj.addWord(word)
# param_2 = obj.search(word)
74 changes: 74 additions & 0 deletions spiral-matrix/haklee.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
"""searchμ‹œ: TC: O(m*n), SC: O(1)
아이디어:
2차원 λ°°μ—΄μ—μ„œ 아직 ν›‘κ³  가지 μ•Šμ€ μ˜μ—­μ„ β†’, ↓, ←, ↑ λ°©ν–₯으둜 ν›‘λŠ”λ‹€. μ΄λ•Œ, ν•œ λ²ˆμ— ν›‘κ³  갈 μ„ μ˜
μ‹œμž‘κ³Ό 끝 역할을 ν•  κ°’λ“€(즉, boundary κ°’λ“€)을 잘 관리해쀀닀.
- top, bottom, left, right의 역할을 ν•  값을 각각 0, m, 0, n으둜 μ΄ˆκΈ°ν™”.
- β†’ λ°©ν–₯으둜 ν›‘κ³  λ‚˜μ„œ top을 ν•œ μΉΈ μ•„λž˜λ‘œ(즉, top++).
- ↓ λ°©ν–₯으둜 ν›‘κ³  λ‚˜μ„œ rightλ₯Ό ν•œ μΉΈ μ™Όμͺ½μœΌλ‘œ(즉, right--).
- ← λ°©ν–₯으둜 ν›‘κ³  λ‚˜μ„œ bottom을 ν•œ μΉΈ μœ„λ‘œ(즉, bottom--).
- ↑ λ°©ν–₯으둜 ν›‘κ³  λ‚˜μ„œ leftλ₯Ό ν•œ μΉΈ 였λ₯Έμͺ½μœΌλ‘œ(즉, left++).
- rightκ°€ left보닀 μ™Όμͺ½μ— μžˆκ±°λ‚˜ top이 bottom보닀 μ•„λž˜ 있으면 탐색 μ’…λ£Œ.
SC:
- boundary κ°’λ§Œ 관리. O(1).
TC:
- λ°°μ—΄μ˜ λͺ¨λ“  μ•„μ΄ν…œμ— μ •ν™•νžˆ ν•œ λ²ˆμ”© μ ‘κ·Ό. O(m*n).
- 선을 ν•œ 번 κΈ‹λŠ” κ³Όμ •μ—μ„œ μΌμ–΄λ‚˜λŠ” 일이 총 O(1)인데(μ½”λ“œ μ°Έμ‘°), 이게 아무리 λ§Žμ•„λ„ O(m*n)을 λ„˜μ§€λŠ”
λͺ»ν•œλ‹€. ν•œ 선에 μ΅œμ†Œ ν•˜λ‚˜μ˜ 값은 λ“€μ–΄μžˆκΈ° λ•Œλ¬Έ.
- μ’…ν•©ν•˜λ©΄ O(m*n).
"""


class Solution:
def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
def read_line(start: tuple[int, int], end: tuple[int, int]) -> list[int]:
if start[0] == end[0]:
# column λ°©ν–₯
s, e = sorted([start[1], end[1]]) # TC: O(1)
line = range(s, e + 1)
if start[1] > end[1]: # TC: O(1)
line = reversed(line)
return [matrix[i][start[0]] for i in line]
else:
# row λ°©ν–₯
s, e = sorted([start[0], end[0]]) # TC: O(1)
line = range(s, e + 1)
if start[0] > end[0]: # TC: O(1)
line = reversed(line)
return [matrix[start[1]][i] for i in line]

top, bottom, left, right = 0, len(matrix) - 1, 0, len(matrix[0]) - 1
sol = []
while True:
# μœ„
if right < left:
break
line = read_line((left, top), (right, top))
sol += line
top += 1 # TC: O(1)

# 였λ₯Έμͺ½
if top > bottom:
break
line = read_line((right, top), (right, bottom))
sol += line
right -= 1 # TC: O(1)

# μ•„λž˜
if right < left:
break
line = read_line((right, bottom), (left, bottom))
sol += line
bottom -= 1 # TC: O(1)

# μ™Όμͺ½
if top > bottom:
break
line = read_line((left, bottom), (left, top))
sol += line
left += 1 # TC: O(1)

return sol
45 changes: 45 additions & 0 deletions valid-parentheses/haklee.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"""TC: O(n), SC: O(n)
λ¬Έμžμ—΄ 길이 n
아이디어:
- λ¬Έμžμ—΄μ„ μ•žμ—μ„œλΆ€ν„° ν›‘μœΌλ©΄μ„œ
- κ΄„ν˜Έ μ‹œμž‘μ„ λ°œκ²¬ν•˜λ©΄ μŠ€νƒμ— λ„£λŠ”λ‹€.
- κ΄„ν˜Έ 끝을 λ°œκ²¬ν•˜λ©΄ μŠ€νƒμ˜ 제일 λ§ˆμ§€λ§‰μ— μžˆλŠ” μ•„μ΄ν…œμ„ popν•΄μ„œ 맀칭이 λ˜λŠ”μ§€ ν™•μΈν•œλ‹€.
- μ΄λ•Œ λ‹€μŒκ³Ό 같은 μ˜ˆμ™Έ 상황듀을 μ‘°μ‹¬ν•œλ‹€.
- μŠ€νƒμ— μ•„μ΄ν…œμ΄ ν•˜λ‚˜λ„ μ—†λŠ”λ° pop을 ν•˜λ €λŠ” 상황 방지.
- e.g.) "))))"
- λͺ¨λ“  λ¬Έμžμ—΄μ„ ν›‘κ³  μ§€λ‚˜κ°”λŠ”λ° μŠ€νƒμ— μ•„μ΄ν…œμ΄ λ‚¨μ•„μžˆλŠ” κ²½μš°λ„ μ‹€νŒ¨λ‹€.
- e.g.) "(((("
SC:
- μ‹œμž‘ κ΄„ν˜Έ 리슀트 O(1).
- 끝 κ΄„ν˜Έμ™€ λ§€μΉ­λ˜λŠ” μ‹œμž‘ κ΄„ν˜Έ dict O(1).
- μ‹œμž‘ κ΄„ν˜Έλ§Œ μžˆλŠ” 경우 μŠ€νƒμ— μŒ“μ΄λŠ” μ•„μ΄ν…œμ€ 총 nκ°œλ‹€. O(n).
- μ’…ν•©ν•˜λ©΄ O(n).
TC:
- 문자 총 nκ°œμ— λŒ€ν•΄ μ•„λž˜λ₯Ό λ°˜λ³΅ν•œλ‹€.
- μ‹œμž‘ κ΄„ν˜ΈμΈμ§€ 체크. O(1).
- μ‹œμž‘ κ΄„ν˜ΈμΈ 경우 μŠ€νƒμ— μŒ“κΈ° O(1).
- 끝 κ΄„ν˜ΈμΈ 경우 μŠ€νƒμ—μ„œ popν• λ•Œ O(1), κ΄„ν˜Έ 맀칭 μ²΄ν¬μ‹œ O(1).
- μ’…ν•©ν•˜λ©΄ O(n).
"""


class Solution:
def isValid(self, s: str) -> bool:
stack = []
openings = ["(", "{", "["]
ending_match = {
")": "(",
"}": "{",
"]": "[",
}
for c in s:
if c in openings:
stack.append(c)
else:
if not stack or ending_match[c] != stack.pop():
return False
return False if stack else True

0 comments on commit ddd3676

Please sign in to comment.