Skip to content

Commit 4d7221d

Browse files
authored
Merge pull request #1338 from shinsj4653/main
[shinsj4653] Week 04 Solutions
2 parents 8c7f94d + afe0d4a commit 4d7221d

File tree

5 files changed

+394
-0
lines changed

5 files changed

+394
-0
lines changed

coin-change/shinsj4653.py

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
"""
2+
[문제풀이]
3+
# Inputs
4+
- 정수 배열 coins
5+
- 총 돈의 값 amount
6+
# Outputs
7+
- amount 를 채울 수 있는 동전의 가장 적은 수
8+
- 만약 만들 수 없다면 -1 return
9+
# Constraints
10+
- 1 <= coins.length <= 12
11+
- 1 <= coins[i] <= 2^31 - 1
12+
- 0 <= amount <= 10^4
13+
# Ideas
14+
- 우선 이전 풀이 본 거 연습해보기
15+
- DP 탑다운 방식으로! 이 문제 풀이를 내가 100% 이해하고 있는게 맞는지 손으로 도식화 해보기로함
16+
17+
18+
[회고]
19+
재귀랑 dp는 다양한 유형을 많이 풀어보는 수 밖에..
20+
"""
21+
22+
23+
class Solution:
24+
def coinChange(self, coins: List[int], amount: int) -> int:
25+
memo = {}
26+
27+
def dp(amount):
28+
29+
if amount == 0:
30+
return 0
31+
32+
retList = []
33+
for coin in coins:
34+
if amount - coin >= 0:
35+
if amount - coin not in memo:
36+
memo[amount - coin] = dp(amount - coin)
37+
38+
if memo[amount - coin] != -1:
39+
retList.append(memo[amount - coin])
40+
41+
return min(retList) + 1 if retList else -1
42+
43+
return dp(amount)
44+
45+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
"""
2+
[문제풀이]
3+
# Inputs
4+
- sorted rotated array : nums
5+
- nums안의 요소는 unique
6+
# Outputs
7+
- 배열의 가장 작은 값 Return
8+
# Constraints
9+
- O(logN) 시간대로 풀어야함
10+
- n == nums.length
11+
- 1 <= n <= 5000
12+
- -5000 <= nums[i] <= 5000
13+
- All the integers of nums are unique.
14+
- nums is sorted and rotated between 1 and n times.
15+
# Ideas
16+
그냥 정렬은 O(NlogN) 이어서 불가능
17+
rotate : 맨 끝의 요소가 맨 처음으로 옴
18+
이진탐색이 O(logN) 이긴한데..->하지만, 이진탐색은 정렬된 배열에서만 사용가능
19+
그리고, 이 문제에선 아닌 것 같다
20+
21+
끝의 원소를 빼서 stack에 append -> 모두 o(1)
22+
23+
회전되어 있는 배열의 특성을 활용하여
24+
-> 끝의 원소 빼고, 그걸 stack 에 넣기
25+
-> 그리고 stack의 맨 끝 원소보다 nums의 끝 원소가 더 클때
26+
stack[-1] 이 정답
27+
-> 근데 이건 o(n) 아닌가??
28+
29+
우선 내 풀이 정답
30+
해설 참고
31+
-> 내 풀이는 O(n) 이다.. O(logN) 풀이가 필요
32+
이분탐색 응용문제이다
33+
34+
[회고]
35+
36+
"""
37+
38+
# 내 풀이
39+
from collections import deque
40+
41+
42+
class Solution:
43+
def findMin(self, nums: List[int]) -> int:
44+
45+
if len(nums) == 1:
46+
return nums[0]
47+
48+
nums = deque(nums)
49+
50+
st = []
51+
ret = 0
52+
53+
while nums:
54+
num = nums.pop()
55+
56+
if not nums:
57+
ret = num
58+
break
59+
60+
if num < nums[-1]:
61+
ret = num
62+
break
63+
64+
return ret
65+
66+
# 해설
67+
class Solution:
68+
def findMin(self, nums: List[int]) -> int:
69+
70+
left, right = 1, len(nums) - 1
71+
72+
while left <= right:
73+
mid = (left + right) // 2
74+
if nums[mid - 1] > nums[mid]:
75+
return nums[mid]
76+
if nums[0] < nums[mid]:
77+
left = mid + 1
78+
else:
79+
right = mid - 1
80+
81+
return nums[0]
82+
83+
+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
"""
2+
[문제풀이]
3+
# Inputs
4+
- 이진 트리의 root
5+
# Outputs
6+
- 가장 최고 깊이
7+
# Constraints
8+
The number of nodes in the tree is in the range [0, 104].
9+
-100 <= Node.val <= 100
10+
# Ideas
11+
dfs, 즉 재귀 돌면서
12+
depth 를 max로 업데이트 하면 될 것 같은 느낌?
13+
14+
[회고]
15+
내 풀이는 정답
16+
해설 방법도 궁금하여 참고
17+
-> TC, SC도 파악하는 연습!
18+
19+
TC: o(n)
20+
SC: o(n)
21+
22+
"""
23+
24+
# 내 풀이
25+
# Definition for a binary tree node.
26+
# class TreeNode:
27+
# def __init__(self, val=0, left=None, right=None):
28+
# self.val = val
29+
# self.left = left
30+
# self.right = right
31+
class Solution:
32+
def maxDepth(self, root: Optional[TreeNode]) -> int:
33+
def dfs(node, depth):
34+
if node is None:
35+
return depth - 1
36+
37+
return max(dfs(node.left, depth + 1), dfs(node.right, depth + 1))
38+
39+
return dfs(root, 1)
40+
# 해설
41+
# bfs 풀이도 존재
42+
class Solution:
43+
def maxDepth(self, root: Optional[TreeNode]) -> int:
44+
if not root:
45+
return 0
46+
max_depth = 0
47+
stack = [(root, 1)]
48+
while stack:
49+
node, depth = stack.pop()
50+
max_depth = max(depth, max_depth)
51+
if node.left:
52+
stack.append((node.left, depth + 1))
53+
if node.right:
54+
stack.append((node.right, depth + 1))
55+
return max_depth
56+

merge-two-sorted-lists/shinsj4653.py

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
"""
2+
[문제풀이]
3+
# Inputs
4+
- two sorted linked lists
5+
# Outputs
6+
- 두 링크드 리스트를 합쳐서 하나의 정렬된 (오름차순) 리스트 반환
7+
# Constraints
8+
- The number of nodes in both lists is in the range [0, 50].
9+
- -100 <= Node.val <= 100
10+
- Both list1 and list2 are sorted in non-decreasing order.
11+
# Ideas
12+
두 링크드 리스트는 모두 오름차순으로 정렬되어 있음
13+
-> ListNode는 val, next 로 되어있음
14+
15+
우선 두 리스트 이어붙이고,
16+
먼가 리스트 정렬 알고리즘 써야할듯?
17+
리스트라서, 두 노드를 바꾸는 swap() 함수 쓰면서,
18+
왼쪽보다 오른쪽이 작으면 바꾸는 식으로 하면 될듯?
19+
20+
즉, 붙어있는 두 노드 비교하면서 쭉 돌기
21+
하지만 인덱스가 없어서 어떻게 순회할지?
22+
-> point라는 기준을 둬서 이 point를 기준으로 prev, next를 만들어서 순회
23+
-> 근데 prev, next만으로는 swap이 어려워서 2개가 아닌 3개를 둬야할 것 같은데,
24+
구현 방법이 떠오르지 않아서 해설 참고
25+
26+
해설 참고
27+
- 기존 리스트 변경이 아닌, 아예 새로운 리스트를 재창조 하는 방식으로!
28+
29+
30+
[회고]
31+
기존 리스트를 swap하려고 하다 보니, 어렵게 생각하게됨..
32+
33+
"""
34+
35+
36+
# Definition for singly-linked list.
37+
# class ListNode:
38+
# def __init__(self, val=0, next=None):
39+
# self.val = val
40+
# self.next = next
41+
class Solution:
42+
def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
43+
44+
retList = ListNode(None)
45+
head = retList
46+
47+
while list1 and list2:
48+
if list1.val < list2.val:
49+
head.next = list1
50+
list1 = list1.next
51+
52+
else:
53+
head.next = list2
54+
list2 = list2.next
55+
56+
head = head.next
57+
58+
head.next = list1 or list2
59+
return retList.next
60+

word-search/shinsj4653.py

+150
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
"""
2+
[문제풀이]
3+
# Inputs
4+
- board: m*n grid of characters
5+
- word: str
6+
# Outputs
7+
- word 가 grid 안에 있으면 true, 아니면 false
8+
# Constraints
9+
- 탐색: 상하좌우
10+
- m == board.length
11+
- n = board[i].length
12+
- 1 <= m, n <= 6
13+
- 1 <= word.length <= 15
14+
15+
- board, word => 무조건 대소문자로 구성
16+
# Ideas
17+
1. 퍼지면서 탐색 -> bfs?
18+
q = cur.append(i, j, "")
19+
q.pop() 해서
20+
if 현재 w 가 word랑 같다면 그 즉시 bfs stop하고 return True
21+
만약 bfs 끝까지 했는데도 안나오면 return False
22+
23+
bfs: q에 다음 원소 넣을 때 현재 값에 이어붙인문자가 w랑 어떤식으로 비교해야 맞는 조건절이 되는걸까?
24+
=> cur_w의 len 값을 i로 사용하려했지만 w가 더 짧으면 idxError 뜰까봐 보류
25+
=> 메모리 초과 오류 뜸..
26+
=> 아..같은 자리를 방문하면 안됨!! 즉, 원복이 필요함!
27+
-> 백트래킹으로 풀이 change
28+
29+
2. dfs로도 꼭 풀어보기!
30+
백트래킹 복습 용으로 굿
31+
32+
board안의 숫자는 오직 대소문자 -> isalpha() 로 체킹 가능
33+
=> 방문하면 0으로 바꾸기
34+
35+
풀기는 풀었지만..7090ms : Beats 7.34%
36+
37+
Follow up : Could you use search pruning to make your solution faster with a larger board
38+
가지치기 기법 어떻게 도입할까??
39+
=> cur_idx 하나 둬서, AB.. ABC -> 진행 도중, 하나라도 word랑 다르면 바로 그 경로 컷
40+
=> 그래도 4587ms.. Beats 41.00%
41+
=> 먼가 더 정석 성능 개선이 필요
42+
43+
해설 참고
44+
=> word_idx를 이용, any문을 이용한 리팩토링
45+
=> 해설 풀이 : 4385ms
46+
47+
[회고]
48+
idx를 이용한 가지치기 방법 잘 알아두자
49+
"""
50+
51+
# from collections import deque
52+
# class Solution:
53+
# def exist(board, word):
54+
#
55+
# q = deque([])
56+
# n, m = len(board), len(board[0])
57+
#
58+
# q.append((0, 0, board[0][0]))
59+
#
60+
# dy = [-1, 0, 1, 0]
61+
# dx = [0, 1, 0, -1]
62+
#
63+
# while q:
64+
# cur_y, cur_x, cur_w = q.popleft()
65+
#
66+
# if cur_w == word:
67+
# return True
68+
#
69+
# for i in range(3):
70+
# ny = cur_y + dy[i]
71+
# nx = cur_x + dx[i]
72+
#
73+
# if 0 <= ny < n and 0 <= nx < m:
74+
# q.append((ny, nx, cur_w + board[ny][nx]))
75+
#
76+
# return False
77+
#
78+
# exist([["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], "ABCCDE")
79+
80+
81+
class Solution:
82+
def exist(self, board: List[List[str]], word: str) -> bool:
83+
84+
n, m = len(board), len(board[0])
85+
86+
dy = [-1, 0, 1, 0]
87+
dx = [0, 1, 0, -1]
88+
89+
v = [[False for _ in range(m)] for _ in range(n)]
90+
91+
def dfs(y, x, w):
92+
#print('y, x : ', y, x)
93+
#print('w: ', w)
94+
if w == word:
95+
return True
96+
97+
if len(w) >= len(word):
98+
return False
99+
100+
for k in range(4):
101+
ny = y + dy[k]
102+
nx = x + dx[k]
103+
104+
if 0 <= ny < n and 0 <= nx < m and not v[ny][nx]:
105+
v[ny][nx] = True
106+
if dfs(ny, nx, w + board[ny][nx]):
107+
return True
108+
v[ny][nx] = False
109+
110+
for i in range(n):
111+
for j in range(m):
112+
if not v[i][j] and board[i][j] == word[0]:
113+
v[i][j] = True
114+
if dfs(i, j, board[i][j]):
115+
return True
116+
v[i][j] = False
117+
118+
return False
119+
120+
# 해설
121+
class Solution:
122+
def exist(self, board: List[List[str]], word: str) -> bool:
123+
124+
n, m = len(board), len(board[0])
125+
126+
dy = [-1, 0, 1, 0]
127+
dx = [0, 1, 0, -1]
128+
129+
def dfs(y, x, idx):
130+
if idx == len(word):
131+
return True
132+
133+
if not (0 <= y < n and 0 <= x < m):
134+
return False
135+
136+
if board[y][x] != word[idx]:
137+
return False
138+
139+
temp = board[y][x]
140+
board[y][x] = ""
141+
142+
for i in range(4):
143+
if dfs(y + dy[i], x + dx[i], idx + 1):
144+
return True
145+
146+
board[y][x] = temp
147+
return False
148+
149+
return any(dfs(i, j, 0) for i in range(n) for j in range(m))
150+

0 commit comments

Comments
 (0)