Skip to content

Commit 9ebe4bc

Browse files
authored
Merge branch 'DaleStudy:main' into main
2 parents 66e51b0 + 2fd52b4 commit 9ebe4bc

File tree

101 files changed

+2887
-0
lines changed

Some content is hidden

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

101 files changed

+2887
-0
lines changed

3sum/devyejin.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
class Solution:
2+
def threeSum(self, nums: List[int]) -> List[List[int]]:
3+
nums.sort() # O(n)
4+
5+
n = len(nums)
6+
result = []
7+
8+
for i in range(n - 2):
9+
# target을 잡을때도 이전에 구했다면 패스
10+
if i > 0 and nums[i] == nums[i - 1]:
11+
continue
12+
13+
target = - nums[i]
14+
left, right = i + 1, n - 1
15+
16+
while left < right:
17+
two_sum = nums[left] + nums[right]
18+
19+
if two_sum == target:
20+
result.append([nums[i], nums[left], nums[right]])
21+
22+
while left < right and nums[left] == nums[left + 1]:
23+
left += 1
24+
25+
while left < right and nums[right] == nums[right - 1]:
26+
right -= 1
27+
28+
left += 1
29+
right -= 1
30+
31+
elif two_sum < target:
32+
left += 1
33+
else:
34+
right -= 1
35+
36+
return result

climbing-stairs/devyejin.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
class Solution(object):
2+
def climbStairs(self, n):
3+
"""
4+
:type n: int
5+
:rtype: int
6+
"""
7+
if n <= 2:
8+
return n
9+
10+
dp = [0] * (n + 1)
11+
dp[1], dp[2] = 1, 2
12+
13+
for i in range(3, n + 1):
14+
dp[i] = dp[i-1] + dp[i-2]
15+
16+
return dp[n]
17+

coin-change/hyer0705.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
function coinChange(coins: number[], amount: number): number {
2+
// dp[i] = i 금액을 만드는 데 필요한 최소 동전의 갯수...
3+
const dp: number[] = Array(amount + 1).fill(Infinity);
4+
dp[0] = 0;
5+
6+
for (let i = 1; i <= amount; i++) {
7+
let min = Infinity;
8+
for (const coin of coins) {
9+
if (i >= coin) {
10+
min = Math.min(dp[i - coin] + 1, min);
11+
}
12+
}
13+
dp[i] = min;
14+
}
15+
16+
return Number.isFinite(dp[amount]) ? dp[amount] : -1;
17+
}

coin-change/hyunjung-choi.kt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* 시간복잡도: O(amount × coins.length)
3+
* 공간복잡도: O(amount)
4+
*/
5+
6+
class Solution {
7+
fun coinChange(coins: IntArray, amount: Int): Int {
8+
val dp = IntArray(amount + 1) { Int.MAX_VALUE }
9+
dp[0] = 0
10+
11+
for (i in 1..amount) {
12+
for (coin in coins) {
13+
if (i - coin >= 0 && dp[i - coin] != Int.MAX_VALUE) {
14+
dp[i] = minOf(dp[i], dp[i - coin] + 1)
15+
}
16+
}
17+
}
18+
19+
return if (dp[amount] == Int.MAX_VALUE) -1 else dp[amount]
20+
}
21+
}

combination-sum/devyejin.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
class Solution:
2+
def combinationSum(self, candidates: list[int], target: int) -> list[list[int]]:
3+
4+
def backtracking(start, total, result):
5+
if total == target:
6+
answer.append(result[:])
7+
return
8+
9+
if sum(result) > target:
10+
return
11+
12+
for i in range(start, len(candidates)):
13+
result.append(candidates[i])
14+
backtracking(i, total + candidates[i], result)
15+
result.pop()
16+
17+
answer = []
18+
backtracking(0, 0, [])
19+
return answer
20+
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/**
2+
* @param {number[]} candidates
3+
* @param {number} target
4+
* @return {number[][]}
5+
*/
6+
7+
/**
8+
* candidates를 여러번 사용해도 된다. 하지만 사용한 종류와 개수가 모두 같으면 안된다.
9+
*
10+
*/
11+
var combinationSum = function(candidates, target) {
12+
const candidatesLength = candidates.length
13+
// 시작 시점에서 array를 만들어서 넘겨줘야한다.
14+
// candidates 중에 넣으면 target이 되면 답에 그 배열을 넣고 탈출한다.
15+
// 만약 더했는데 target보다 크면 그냥 리턴한다.
16+
// target보다 작은것에 대해서 넣는다.
17+
const ret = []
18+
function dp(total,newNum,currentArr){
19+
if(total + newNum > target){
20+
return
21+
}
22+
if(total + newNum == target && ){
23+
ret.push([...currentArr,newNum]);
24+
return
25+
}
26+
27+
//두 가지 어느것에도 해당하지 않으면 재귀를 또 다시 돈다.
28+
for(let i = 0; i<candidatesLength; i++){
29+
dp(total+newNum , candidates[i],[...currentArr,candidates[i]])
30+
}
31+
}
32+
dp(0,0,[])
33+
return ret
34+
};
35+
36+
//여기서 문제가 생겼다.
37+
// 중복이 생긴다는 것이다. 어떻게 중복을 제거하면 좋을까?
38+
/**
39+
* 1. Set을 이용한다.
40+
* 2. 순서를 둔다. idx를 dfs에 넘겨주어서, 순서대로 작동하게 한다.
41+
*/
42+
43+
var combinationSum = function(candidates, target) {
44+
const candidatesLength = candidates.length
45+
const ret = []
46+
function dp(idx,total,currentArr){
47+
if(total > target){
48+
return
49+
}
50+
if(total == target){
51+
ret.push(currentArr);
52+
return
53+
}
54+
55+
//idx를 넘겨받아서, 그 이후의 것에만(자기 자신 포함) 돌게 된다. 그러면 절반정도만 돈다고 볼 수 있다.
56+
for(let i = idx; i < candidatesLength; i++){
57+
dp(i,total+ candidates[i],[...currentArr,candidates[i]])
58+
}
59+
}
60+
dp(0,0,[])
61+
return ret
62+
};
63+
64+
65+
66+
/**
67+
시간복잡도: O(N^(target/min)) : N개 후보 중 선택하는 경우의 수가 target/min 깊이만큼 반복
68+
공간복잡도: O(target/min) : 재귀 스택의 최대 깊이가 target/min
69+
70+
71+
*/
72+
73+
74+
// 2. dp를 활용한 문제 해결방법
75+
var combinationSum = function(candidates, target) {
76+
const dp = Array.from({length:target+1},()=>[])
77+
dp[0] = [[]];
78+
for(let candidate of candidates){
79+
//여기서 candidate에 대해서, 이후 타겟까지 더할 수있는 숫자에 대한 조합에, candidate를 각각 넣어준다.
80+
for(let i = candidate; i <= target; i++){
81+
for(let comb of dp[i-candidate]){ //각 조합에 넣어줌
82+
dp[i].push([...comb,candidate])
83+
}
84+
}
85+
}
86+
return dp[target]
87+
};
88+
/**
89+
시간복잡도: O(N × target × M)
90+
N개 후보를 순회하면서, 각 후보마다 target까지의 값들에 대해 기존 조합들을 복사해서 새 조합을 생성하는데, 기존의 조합의 수 M을 곱해야함
91+
공간복잡도: O(target × M)
92+
dp 배열의 각 인덱스에 해당 값을 만드는 모든 조합들을 저장. 조합개수에 따라서 커짐
93+
*/

combination-sum/hyer0705.ts

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

combination-sum/jongwanra.py

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
"""
2+
[Problem]
3+
https://leetcode.com/problems/combination-sum/
4+
5+
candidates: unique array of integers
6+
return a list of all unique combinations of candidates == target
7+
any order
8+
9+
하나의 숫자는 candidates에서 무제한으로 선택할 수 있다.
10+
두 조합이 서로 다르다고 간주되는 조건은, 선택된 숫자 중 적어도 하나의 개수가 다를 때이다.
11+
[Brainstorming]
12+
DFS를 이용해서 Combination을 만든다.
13+
종료조건: target == sum || target > sum
14+
15+
[Plan]
16+
1. candidates를 오름차순 정렬
17+
2. DFS
18+
19+
[Complexity]
20+
N -> candidates.length
21+
M -> approximately target divided by the smallest candidate. -> target / min(candidates)
22+
Time: O(N^M)
23+
Space: O(N + M)
24+
- 재귀 호출 스택: 깊이는 최대 target / min(candidates)
25+
- chosen: 재귀 스택 깊이 만큼 공간 차지
26+
- cache: 최악의 경우 answer와 같은 개수의 조합 저장 -> O(number of combinations)
27+
"""
28+
29+
from typing import List
30+
31+
32+
class Solution:
33+
def combinationSum1(self, candidates: List[int], target: int) -> List[List[int]]:
34+
cache = set()
35+
answer = []
36+
chosen = []
37+
38+
def dfs(sum: int) -> None:
39+
nonlocal target, candidates, cache, answer, chosen
40+
print(chosen)
41+
if sum > target:
42+
return
43+
if sum == target:
44+
copied_chosen = chosen[:]
45+
copied_chosen.sort()
46+
47+
cache_key = tuple(copied_chosen)
48+
if cache_key in cache:
49+
# print(f"already exists {cache_key} in cache")
50+
return
51+
cache.add(cache_key)
52+
answer.append(copied_chosen)
53+
54+
for candidate in candidates:
55+
chosen.append(candidate)
56+
dfs(sum + candidate)
57+
chosen.pop()
58+
59+
dfs(0)
60+
return answer
61+
62+
"""
63+
중복 조합 방지 another solution
64+
ref: https://www.algodale.com/problems/combination-sum/
65+
66+
[Complexity]
67+
N -> candidates.length
68+
M -> target / min(candidates)
69+
Time: O(N^M)
70+
Space: O(M)
71+
"""
72+
73+
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
74+
answer = []
75+
combi = []
76+
77+
def dfs(sum: int, start: int) -> None:
78+
nonlocal target, answer, combi, candidates
79+
80+
if sum > target:
81+
return
82+
if sum == target:
83+
answer.append(combi[:])
84+
return
85+
86+
for index in range(start, len(candidates)):
87+
candidate = candidates[index]
88+
combi.append(candidate)
89+
dfs(sum + candidate, index)
90+
combi.pop()
91+
92+
dfs(0, 0)
93+
return answer
94+
95+
96+
sol = Solution()
97+
# print(sol.combinationSum([2,3,6,7], 7))
98+
print(sol.combinationSum([2, 3, 5], 8))
99+
# print(sol.combinationSum([2], 1))
100+

combination-sum/jun0811.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* @param {number[]} candidates
3+
* @param {number} target
4+
* @return {number[][]}
5+
*/
6+
var combinationSum = function (candidates, target) {
7+
const result = [];
8+
candidates.sort((a, b) => a - b);
9+
function backTracking(start, arr, total) {
10+
if (total == target) {
11+
result.push([...arr]);
12+
return;
13+
}
14+
15+
for (let i = start; i < candidates.length; i++) {
16+
const cur = candidates[i];
17+
if (cur + total > target) {
18+
return;
19+
}
20+
21+
backTracking(i, [...arr, cur], total + cur);
22+
}
23+
}
24+
25+
backTracking(0, [], 0);
26+
return result;
27+
};

combination-sum/prograsshopper.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
class Solution:
2+
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
3+
# Time complexity: O(n ^ (T / m))
4+
result = []
5+
6+
def dfs(remain_sum, index, path):
7+
if remain_sum < 0:
8+
return
9+
if remain_sum == 0:
10+
result.append(path)
11+
return
12+
13+
for i in range(index, len(candidates)):
14+
dfs(remain_sum - candidates[i], i, path + [candidates[i]])
15+
16+
dfs(target, 0, [])
17+
return result

0 commit comments

Comments
 (0)