Skip to content

Commit 756d0ea

Browse files
committed
2 parents feaa599 + daa942f commit 756d0ea

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

88 files changed

+3091
-1
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
* @DaleStudy/coach

.github/pull_request_template.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
## 답안 제출 문제
2+
3+
<!--
4+
자신의 수준이나 일정에 맞게 금주에 푸시기로 정한 문제들만 나열해주세요.
5+
코드 검토자들이 PR 승인 여부를 결정할 때 도움이 됩니다.
6+
-->
7+
8+
- [ ] 문제 1
9+
- [ ] 문제 2
10+
- [ ] 문제 3
11+
12+
## 체크 리스트
13+
14+
- [ ] PR을 프로젝트에 추가하고 Week를 현재 주차로 설정해주세요.
15+
- [ ] 바로 앞에 PR을 열어주신 분을 코드 검토자로 지정해주세요.
16+
- [ ] 문제를 모두 푸시면 프로젝트에서 Status를 `In Review`로 설정해주세요.
17+
- [ ] 코드 검토자 1분 이상으로부터 승인을 받으셨다면 PR을 병합해주세요.

.github/workflows/integration.yaml

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,21 @@ jobs:
88
runs-on: ubuntu-latest
99
steps:
1010
- uses: actions/checkout@v4
11-
- uses: fernandrone/[email protected]
11+
with:
12+
fetch-depth: 0
13+
14+
- name: Find files missing end line break
15+
run: |
16+
files=$(git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.sha }})
17+
success=true
18+
for file in $files; do
19+
if [ "$(tail -c 1 $file | wc -l)" -eq 0 ]; then
20+
echo "- $file" >> $GITHUB_STEP_SUMMARY
21+
success=false
22+
fi
23+
done
24+
25+
if [ "$success" = false ]; then
26+
echo -e "\n:warning: 위 파일들의 끝에 누락된 줄 바꿈을 추가해 주세요." >> $GITHUB_STEP_SUMMARY
27+
exit 1
28+
fi

climbing-stairs/EGON.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
from unittest import TestCase, main
2+
3+
4+
class Solution:
5+
def climbStairs(self, n: int) -> int:
6+
return self.solveWithDP(n)
7+
8+
"""
9+
Runtime: 30 ms (Beats 83.62%)
10+
Time Complexity: O(n)
11+
> 3에서 n + 1 까지 range를 조회하였으므로 O((n + 1) - 3) ~= O(n)
12+
13+
Memory: 16.39 MB (Beats 90.15%)
14+
Space Complexity: O(n)
15+
> 크기가 n + 1인 dp를 선언하여 사용했으므로 O(n + 1) ~= O(n)
16+
"""
17+
def solveWithDP(self, n: int) -> int:
18+
if n <= 2:
19+
return n
20+
21+
dp = [0] * (n + 1)
22+
dp[0], dp[1], dp[2] = 0, 1, 2
23+
for stair in range(3, n + 1):
24+
dp[stair] = dp[stair - 1] + dp[stair - 2]
25+
26+
return dp[n]
27+
28+
29+
class _LeetCodeTestCases(TestCase):
30+
def test_1(self):
31+
n = 2
32+
output = 2
33+
self.assertEqual(Solution.climbStairs(Solution(), n), output)
34+
35+
def test_2(self):
36+
n = 3
37+
output = 3
38+
self.assertEqual(Solution.climbStairs(Solution(), n), output)
39+
40+
def test_3(self):
41+
n = 1
42+
output = 1
43+
self.assertEqual(Solution.climbStairs(Solution(), n), output)
44+
45+
46+
if __name__ == '__main__':
47+
main()

coin-change/EGON.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
from typing import List
2+
from unittest import TestCase, main
3+
from collections import defaultdict
4+
5+
6+
class Solution:
7+
def coinChange(self, coins: List[int], amount: int) -> int:
8+
return self.solve_with_dp(coins, amount)
9+
10+
# Unbounded Knapsack Problem
11+
def solve_with_dp(self, coins: List[int], amount: int) -> int:
12+
if amount == 0:
13+
return 0
14+
15+
coins.sort()
16+
17+
if amount < coins[0]:
18+
return -1
19+
20+
dp = [[0] * (amount + 1) for _ in range(len(coins) + 1)]
21+
for curr_r in range(1, len(coins) + 1):
22+
coin_index = curr_r - 1
23+
curr_coin = coins[coin_index]
24+
if amount < curr_coin:
25+
continue
26+
27+
dp[curr_r][curr_coin] += 1
28+
for curr_amount in range(curr_coin + 1, amount + 1):
29+
for coin in coins:
30+
if 0 < dp[curr_r][curr_amount - coin]:
31+
dp[curr_r][curr_amount] = max(dp[curr_r - 1][curr_amount], dp[curr_r][curr_amount - coin] + 1)
32+
else:
33+
dp[curr_r][curr_amount] = dp[curr_r - 1][curr_amount]
34+
35+
return dp[-1][-1] if 0 < dp[-1][-1] else -1
36+
37+
38+
class _LeetCodeTestCases(TestCase):
39+
def test_1(self):
40+
coins = [1, 2, 5]
41+
amount = 11
42+
output = 3
43+
self.assertEqual(Solution.coinChange(Solution(), coins, amount), output)
44+
45+
def test_2(self):
46+
coins = [2]
47+
amount = 3
48+
output = -1
49+
self.assertEqual(Solution.coinChange(Solution(), coins, amount), output)
50+
51+
def test_3(self):
52+
coins = [1]
53+
amount = 0
54+
output = 0
55+
self.assertEqual(Solution.coinChange(Solution(), coins, amount), output)
56+
57+
def test_4(self):
58+
coins = [1, 2147483647]
59+
amount = 2
60+
output = -1
61+
self.assertEqual(Solution.coinChange(Solution(), coins, amount), output)
62+
63+
64+
if __name__ == '__main__':
65+
main()

combination-sum/EGON.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
from typing import List
2+
from unittest import TestCase, main
3+
from collections import defaultdict
4+
5+
6+
class Solution:
7+
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
8+
return self.solve_with_dfs(candidates, target)
9+
10+
"""
11+
Runtime: 2039 ms (Beats 5.01%)
12+
Time Complexity: ?
13+
14+
Memory: 16.81 MB (Beats 11.09%)
15+
Space Complexity: ?
16+
"""
17+
def solve_with_dfs(self, candidates: List[int], target: int) -> List[List[int]]:
18+
result = []
19+
stack = []
20+
visited = defaultdict(bool)
21+
for candidate in candidates:
22+
stack.append([[candidate], candidate])
23+
24+
while stack:
25+
curr_combination, curr_sum = stack.pop()
26+
curr_visited_checker = tuple(sorted(curr_combination))
27+
28+
if curr_sum == target and visited[curr_visited_checker] is False:
29+
visited[curr_visited_checker] = True
30+
result.append(curr_combination)
31+
32+
if target < curr_sum:
33+
continue
34+
35+
for candidate in candidates:
36+
post_combination, post_sum = curr_combination + [candidate], curr_sum + candidate
37+
stack.append([post_combination, post_sum])
38+
39+
return result
40+
41+
42+
class _LeetCodeTestCases(TestCase):
43+
def test_1(self):
44+
candidates = [2, 3, 6, 7]
45+
target = 7
46+
output = [[2, 2, 3], [7]]
47+
self.assertEqual(Solution.combinationSum(Solution(), candidates, target), output)
48+
49+
def test_2(self):
50+
candidates = [2, 3, 5]
51+
target = 8
52+
output = [[2, 2, 2, 2], [2, 3, 3], [3, 5]]
53+
self.assertEqual(Solution.combinationSum(Solution(), candidates, target), output)
54+
55+
def test_3(self):
56+
candidates = [2]
57+
target = 1
58+
output = []
59+
self.assertEqual(Solution.combinationSum(Solution(), candidates, target), output)
60+
61+
62+
if __name__ == '__main__':
63+
main()
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
from typing import List, Optional
2+
from unittest import TestCase, main
3+
4+
5+
# Definition for a binary tree node.
6+
class TreeNode:
7+
def __init__(self, val=0, left=None, right=None):
8+
self.val = val
9+
self.left = left
10+
self.right = right
11+
12+
13+
class Solution:
14+
def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
15+
return self.solve_1(preorder, inorder)
16+
17+
"""
18+
Runtime: 112 ms (Beats 66.16%)
19+
Time Complexity: O(n ** 2)
20+
Space Complexity: O(n)
21+
Memory: 52.83 MB (Beats 63.14%)
22+
"""
23+
def solve_1(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
24+
index = 0
25+
26+
def build_tree(preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
27+
nonlocal index
28+
29+
if not inorder:
30+
return None
31+
32+
if not 0 <= index < len(preorder):
33+
return None
34+
35+
root = TreeNode(preorder[index])
36+
index += 1
37+
split_index = inorder.index(root.val)
38+
root.left = build_tree(preorder, inorder[:split_index])
39+
root.right = build_tree(preorder, inorder[split_index + 1:])
40+
41+
return root
42+
43+
return build_tree(preorder, inorder)
44+
45+
46+
class _LeetCodeTestCases(TestCase):
47+
def test_1(self):
48+
preorder = [3, 9, 20, 15, 7]
49+
inorder = [9, 3, 15, 20, 7]
50+
output = TreeNode(
51+
val=3,
52+
left=TreeNode(
53+
val=9
54+
),
55+
right=TreeNode(
56+
val=20,
57+
left=TreeNode(val=15),
58+
right=TreeNode(val=7)
59+
)
60+
)
61+
self.assertEqual(Solution.buildTree(Solution(), preorder, inorder), output)
62+
63+
def test_2(self):
64+
preorder = [-1]
65+
inorder = [-1]
66+
output = TreeNode(
67+
val=-1
68+
)
69+
self.assertEqual(Solution.buildTree(Solution(), preorder, inorder), output)
70+
71+
def test_3(self):
72+
preorder = [1, 2]
73+
inorder = [1, 2]
74+
output = TreeNode(
75+
val=1,
76+
right=TreeNode(
77+
val=2
78+
)
79+
)
80+
self.assertEqual(Solution.buildTree(Solution(), preorder, inorder), output)
81+
82+
83+
if __name__ == '__main__':
84+
main()
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
class Solution {
2+
private int i, p;
3+
public TreeNode buildTree(int[] preorder, int[] inorder) {
4+
// Time complexity: O(n)
5+
// Space complexity: O(n)
6+
return builder(preorder, inorder, Integer.MIN_VALUE);
7+
}
8+
9+
private TreeNode builder(int[] preorder, int[] inorder, int stop) {
10+
if (p >= preorder.length) return null;
11+
if (inorder[i] == stop) {
12+
i += 1;
13+
return null;
14+
}
15+
16+
TreeNode node = new TreeNode(preorder[p]);
17+
p += 1;
18+
19+
node.left = builder(preorder, inorder, node.val);
20+
node.right = builder(preorder, inorder, stop);
21+
return node;
22+
}
23+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Definition for a binary tree node.
2+
# class TreeNode:
3+
# def __init__(self, val=0, left=None, right=None):
4+
# self.val = val
5+
# self.left = left
6+
# self.right = right
7+
class Solution:
8+
# T: O(N)
9+
# S: O(N)
10+
def buildTree(self, preorder: List[int], inorder: List[int]) -> Optional[TreeNode]:
11+
# preorder : root - left - right
12+
# inorder : left - root - right
13+
if not preorder and not inorder:
14+
return None
15+
16+
root = TreeNode(preorder[0])
17+
mid = inorder.index(preorder[0])
18+
19+
root.left = self.buildTree(preorder[1 : mid + 1], inorder[:mid])
20+
root.right = self.buildTree(preorder[mid + 1 :], inorder[mid+1:])
21+
22+
return root
23+

0 commit comments

Comments
 (0)