Skip to content

Commit fe0267a

Browse files
authored
Merge branch 'DaleStudy:main' into main
2 parents 230c8a0 + 94473f0 commit fe0267a

45 files changed

Lines changed: 1213 additions & 14 deletions

Some content is hidden

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

coin-change/gcount85.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
"""
2+
# Intuition
3+
dp[n]은 n원을 만드는데 필요한 최소 동전 개수
4+
e.g. n = 11일 때, 11원을 만들기 위한 최소 동전 개수는 11에서 coins의 원소를 뺀 dp 값 + 1이다.
5+
6+
# Complexity
7+
- Time complexity: O(amount * coins.length)인데, coins 배열 길이가 상수라서 무시 => O(amount)
8+
9+
- Space complexity: dp 배열 생성으로 O(amount)
10+
"""
11+
12+
13+
class Solution:
14+
def coinChange(self, coins: list[int], amount: int) -> int:
15+
coins.sort()
16+
INF = float("inf")
17+
dp = [INF] * (amount + 1)
18+
dp[0] = 0
19+
for i in range(amount + 1):
20+
if dp[i] == INF:
21+
continue
22+
for c in coins:
23+
if i + c > amount:
24+
break
25+
dp[i + c] = min(dp[i + c], dp[i] + 1)
26+
return dp[-1] if dp[-1] != INF else -1

coin-change/hwi-middle.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
class Solution {
2+
public:
3+
int coinChange(vector<int>& coins, int amount) {
4+
if (amount < 1)
5+
{
6+
return 0;
7+
}
8+
9+
vector<int> v(amount);
10+
return solve(coins, amount, v);
11+
}
12+
13+
int solve(vector<int>& coins, int amount, vector<int>& count)
14+
{
15+
if (amount < 0) return -1;
16+
if (amount == 0) return 0;
17+
if (count[amount - 1] != 0) return count[amount - 1];
18+
19+
int min = INT_MAX;
20+
for (int coin : coins)
21+
{
22+
int res = solve(coins, amount - coin, count); // coin을 사용
23+
if (res >= 0 && res < min) // 결과가 유효하고 현재 최솟값보다 작으면 업데이트
24+
{
25+
min = res + 1; // coin을 미리 사용하고 찾은 값이므로 1 더함
26+
}
27+
}
28+
29+
count[amount - 1] = (min == INT_MAX) ? -1 : min;
30+
return count[amount - 1];
31+
}
32+
};

coin-change/liza0525.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# 7기 풀이
2+
# 시간 복잡도: O(n * k)
3+
# - 타겟 코인 값(amount, 복잡도 계산에선 n으로 표기)과 coins의 길이 만큼 탐색하며 계산
4+
# 공간 복잡도: O(n)
5+
# - 타겟 코인 값(amount, 복잡도 계산에선 n으로 표기) 만큼의 min_coin_count 계산 array를 생성
6+
class Solution:
7+
# 해당 문제는 현재 갖고 있는 돈으로 각 코인 값을 만드는 데에 동전을 얼마나 쓰는지 계산하여
8+
# 그 조합 중 가장 작은 값을 계속 찾아가는 문제로, min_coin_count를 사용한다.
9+
def coinChange(self, coins: List[int], amount: int) -> int:
10+
min_coin_count = [-1 for _ in range(amount + 1)] # 각 인덱스는 코인 값, value는 해당 코인 값을 만들 수 있는 동전의 개수(만들 수 없을 땐 -1)
11+
min_coin_count[0] = 0 # 코인 값이 0일 때는 동전을 쓰지 않으면 되므로 무조건 0이 된다.
12+
13+
for target_amount in range(1, len(min_coin_count)):
14+
# 각 코인 값에 대해 최소 동전 개수를 찾는다.
15+
for coin in coins:
16+
if target_amount - coin < 0:
17+
# 대상 코인 값보다 체크할 코인 값이 큰 경우에는 조합을 만들 수 없으므로 넘긴다
18+
continue
19+
if min_coin_count[target_amount - coin] < 0:
20+
# target_amount - coin(보수)을 만들 수 없으면 target_amount도 만들 수 없음
21+
# 예시) target=5, coin=3 → 보수 2를 못 만들면 5도 못 만듦
22+
continue
23+
24+
# 위 두 가지 조건만 넘어가면 동전 개수를 min_coin_count[target_amount]에 정해서 넣을 수 있다는 의미
25+
if min_coin_count[target_amount] == -1:
26+
# 값이 -1인 경우에는 처음으로 계산해서 넣는 것이기 때문에
27+
# min_coin_count[target_amount - coin]에다가 1을 더해서(coin 한 개를 추가 한다는 의미) min_coin_count[target_amount]에 할당
28+
min_coin_count[target_amount] = min_coin_count[target_amount - coin] + 1
29+
else:
30+
# 값이 -1이 아닌 경우는 이전에 저장된 동전 개수가 있으므로
31+
# 이전 결과 값과 min_coin_count[target_amount - coin] + 1의 값을 비교하여 더 적은 수를 저장한다.
32+
min_coin_count[target_amount] = min(
33+
min_coin_count[target_amount],
34+
min_coin_count[target_amount - coin] + 1
35+
)
36+
37+
# 모두 계산한 후 min_coin_count[amount]를 반환한다. (== amount를 만드는 동전의 최소 개수)
38+
return min_coin_count[amount]

combination-sum/jiji-hoon96.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
function combinationSum(candidates: number[], target: number): number[][] {}
2+
3+
combinationSum([2, 3, 6, 7], 7); // [[2,2,3], [7]]
4+
combinationSum([2, 3, 5], 8); // [[2,2,2,2],[2,3,3],[3,5]]
5+
combinationSum([2], 1); // []

combination-sum/ohkingtaek.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
class Solution:
2+
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
3+
"""
4+
- 시간복잡도: O(n^2)
5+
- 공간복잡도: O(n)
6+
DFS 사용
7+
1. 모든 조합을 찾기
8+
2. 조합을 찾을 때, 중복된 조합을 방지하기
9+
"""
10+
result = []
11+
12+
def dfs(start, path, total):
13+
if total == target:
14+
result.append(path[:])
15+
return
16+
if total > target:
17+
return
18+
19+
for i in range(start, len(candidates)):
20+
path.append(candidates[i])
21+
dfs(i, path, total + candidates[i])
22+
path.pop()
23+
24+
dfs(0, [], 0)
25+
return result

combination-sum/riveroverflows.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
class Solution:
2+
"""
3+
TC: O(N^(T/M))
4+
- N = len(candidates), T = target, M = min(candidates)
5+
SC: O((T/M) * N^(T/M))
6+
7+
풀이:
8+
백트래킹으로 모든 조합을 탐색하되, 중복 조합 방지를 위해
9+
start 인덱스를 활용하여 이전 후보는 건너뛰고, 같은 후보는 재사용 허용.
10+
path_sum > target이면 가지치기(pruning)하여 불필요한 탐색을 줄임.
11+
"""
12+
def combinationSum(self, candidates: list[int], target: int) -> list[list[int]]:
13+
answer = []
14+
15+
def backtrack(start, path, path_sum):
16+
if path_sum > target:
17+
return
18+
19+
if path_sum == target:
20+
answer.append(path[:])
21+
return
22+
23+
for i in range(start, len(candidates)):
24+
candidate = candidates[i]
25+
path.append(candidate)
26+
path_sum += candidate
27+
backtrack(i, path, path_sum)
28+
path_sum -= candidate
29+
path.pop()
30+
31+
backtrack(0, [], 0)
32+
33+
return answer

combination-sum/soobing3.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
function combinationSum(candidates: number[], target: number): number[][] {
2+
const result: number[][] = [];
3+
4+
function backtracking(start: number, current: number[], remaining: number) {
5+
if(remaining < 0) return;
6+
if(remaining === 0) {
7+
result.push([...current]);
8+
return;
9+
}
10+
11+
for(let i = start; i < candidates.length; i++) {
12+
current.push(candidates[i]);
13+
backtracking(i, current, remaining - candidates[i]);
14+
current.pop();
15+
}
16+
}
17+
backtracking(0, [], target)
18+
return result;
19+
};

decode-ways/jiji-hoon96.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
function numDecodings(s: string): number {}
2+
3+
numDecodings("12"); // 2
4+
numDecodings("226"); // 3
5+
numDecodings("06"); // 0

decode-ways/soobing3.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
function numDecodings(s: string): number {
2+
const n = s.length;
3+
const dp: number[] = new Array(n + 1).fill(0);
4+
dp[0] = 1;
5+
dp[1] = s[0] === '0' ? 0 : 1;
6+
7+
for(let i=2; i<= n; i++) {
8+
const one = Number(s[i-1]);
9+
const two = Number(s[i-2] + s[i-1]);
10+
if(one !== 0) dp[i] += dp[i-1];
11+
if(two >= 10 && two <= 26) dp[i] += dp[i-2];
12+
}
13+
return dp[n];
14+
};
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
"""
2+
# Intuition
3+
이진탐색으로 찾는다.
4+
5+
# Complexity
6+
- Time complexity: nums의 길이 N일때, O(logN)
7+
8+
- Space complexity: 재귀스택 O(logN)
9+
"""
10+
11+
12+
class Solution:
13+
def findMin(self, nums: list[int]) -> int:
14+
l, m, r = 0, len(nums) // 2, len(nums) - 1
15+
16+
def findMinimum(l, m, r):
17+
if l == m or r == m:
18+
return min(nums[l], nums[r])
19+
20+
# 오른쪽 구간
21+
if nums[m] > nums[r]:
22+
return findMinimum(m, (m + r) // 2, r)
23+
24+
# 왼쪽 구간
25+
return findMinimum(l, (l + m) // 2, m)
26+
27+
return findMinimum(l, m, r)

0 commit comments

Comments
 (0)