Skip to content

Commit 645e529

Browse files
authored
Merge branch 'DaleStudy:main' into main
2 parents 5f929c8 + 03ded85 commit 645e529

File tree

155 files changed

+4528
-1
lines changed

Some content is hidden

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

155 files changed

+4528
-1
lines changed

3sum/Yjason-K.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/**
2+
* 세 수의 합이 0이 되는 모든 고유한 조합을 찾는 함수
3+
*
4+
* @param {number[]} nums - 정수 배열
5+
* @returns {number[][]} - 세 수의 합이 0이 되는 조합 배열
6+
*
7+
* 1. 입력 배열 `nums`를 오름차순으로 정렬.
8+
* 2. 이중 반복문을 사용하여 각 요소를 기준으로 `투 포인터(two-pointer)`를 이용해 조합을 탐색.
9+
* 3. 중복 조합을 방지하기 위해 `Set`을 사용하여 결과 조합의 문자열을 저장.
10+
* 4. 조건에 맞는 조합을 `result` 배열에 추가합니다.
11+
*
12+
* 시간 복잡도:
13+
* - 정렬: O(n log n)
14+
* - 이중 반복문 및 투 포인터: O(n^2)
15+
* - 전체 시간 복잡도: O(n^2)
16+
*
17+
* 공간 복잡도:
18+
* - `Set` 및 `result` 배열에 저장되는 고유 조합: O(k), k는 고유한 조합의 수
19+
* - 전체 공간 복잡도: O(n + k)
20+
*/
21+
function threeSum(nums: number[]): number[][] {
22+
const sumSet = new Set<string>();
23+
const result: number[][] = [];
24+
nums.sort((a, b) => a - b);
25+
26+
// 첫 번째 요소를 기준으로 반복문 수행
27+
for (let i = 0; i < nums.length - 2; i++) {
28+
// 정렬 된 상태이기 때문에 시작점을 기준으로 다음 값 중복 비교
29+
if (i > 0 && nums[i] === nums[i - 1]) continue;
30+
31+
let start = i + 1, end = nums.length - 1;
32+
while (start < end) {
33+
const sum = nums[i] + nums[start] + nums[end];
34+
if (sum > 0) {
35+
end--;
36+
} else if (sum < 0) {
37+
start++;
38+
} else {
39+
const triplet = [nums[i], nums[start], nums[end]];
40+
const key = triplet.toString();
41+
if (!sumSet.has(key)) {
42+
sumSet.add(key);
43+
result.push(triplet);
44+
}
45+
start++;
46+
end--;
47+
}
48+
}
49+
}
50+
51+
return result;
52+
}
53+
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/**
2+
* Definition for a binary tree node.
3+
* public class TreeNode {
4+
* int val;
5+
* TreeNode left;
6+
* TreeNode right;
7+
* TreeNode() {}
8+
* TreeNode(int val) { this.val = val; }
9+
* TreeNode(int val, TreeNode left, TreeNode right) {
10+
* this.val = val;
11+
* this.left = left;
12+
* this.right = right;
13+
* }
14+
* }
15+
*/
16+
17+
// preorder에서 맨 왼쪽을 root
18+
// root값을 기반으로 inorder에서 인덱스를 찾는다 그리고 왼쪽 오른쪽 길이를 구한다.
19+
// 다시 buildTree 함수를 재귀하는데 이때 위에서 구한 왼쪽 길이와 오른쪽길이를 참고해서
20+
// 왼쪽 buildTree
21+
// value를 갱신
22+
// 오른쪽 buildTree를 갱신한다.
23+
24+
// 시간복잡도 : O(N^2) -> 한쪽으로 치우친 트리일 경우 O(N)(index of) + T(N-1)이 될 수 있다.
25+
// 위 식을 전개해보면 N + N-1 + N-2 + ... + 1 = N(N+1)/2 = O(N^2)
26+
// 공간복잡도 : O(N) ->리트코드 but N길이의 리스트 크기*N번의 재귀호출이 일어날 수 있다. 따라서 O(N^2)가 아닌가...?
27+
class SolutionGotprgmer {
28+
public TreeNode buildTree(int[] preorder, int[] inorder) {
29+
30+
if(preorder.length == 0 || indexOf(inorder,preorder[0]) == -1){
31+
return null;
32+
}
33+
TreeNode node = new TreeNode();
34+
35+
int root = preorder[0];
36+
int indexOfRoot = indexOf(inorder,root);
37+
int leftCnt = indexOfRoot;
38+
// 찾으면
39+
node.val = root;
40+
node.left = buildTree(Arrays.copyOfRange(preorder,1,1+leftCnt),Arrays.copyOfRange(inorder,0,leftCnt));
41+
node.right = buildTree(Arrays.copyOfRange(preorder,1+leftCnt,preorder.length),Arrays.copyOfRange(inorder,1+leftCnt,inorder.length));
42+
return node;
43+
}
44+
public int indexOf(int[] intArray,int findNum){
45+
for(int i=0;i<intArray.length;i++){
46+
if(findNum==intArray[i]){
47+
return i;
48+
}
49+
}
50+
return -1;
51+
}
52+
53+
}

combination-sum/GangBean.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
class Solution {
2+
public List<List<Integer>> combinationSum(int[] candidates, int target) {
3+
/**
4+
1. understanding
5+
- find all combinations, which sum to target
6+
- can use same number multiple times
7+
2. strategy
8+
- dp[target]: all combination, which sum to target
9+
- dp[n + 1] = dp[n] | dp[1]
10+
- [2,3,6,7], target = 7
11+
- dp[0] = [[]]
12+
- dp[1] = [[]]
13+
- dp[2] = [[2]]
14+
- dp[3] = [[3]]
15+
- dp[4] = dp[2] | dp[2] = [[2,2]]
16+
- dp[5] = dp[2] | dp[3] = [[2,3]]
17+
- dp[6] = dp[2] | dp[4] , dp[3] | dp[3] = [[2,2,2], [3,3]]
18+
- dp[7] = dp[2] | dp[5], dp[3] | dp[4], dp[6] | dp[1], dp[7] = [[2,2,3],]
19+
3. complexity
20+
- time: O(target * N) where N is length of candidates
21+
- space: O(target * N)
22+
*/
23+
List<List<Integer>>[] dp = new List[target + 1];
24+
for (int i = 0; i <= target; i++) {
25+
dp[i] = new ArrayList<>();
26+
}
27+
28+
dp[0].add(new ArrayList<>());
29+
30+
for (int candidate : candidates) {
31+
for (int i = candidate; i <= target; i++) {
32+
for (List<Integer> combination : dp[i - candidate]) {
33+
List<Integer> newCombination = new ArrayList<>(combination);
34+
newCombination.add(candidate);
35+
dp[i].add(newCombination);
36+
}
37+
}
38+
}
39+
40+
return dp[target];
41+
}
42+
}
43+

combination-sum/HerrineKim.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// 시간 복잡도 : O(n^2)
2+
// 공간 복잡도 : O(n)
3+
4+
/**
5+
* @param {number[]} candidates
6+
* @param {number} target
7+
* @return {number[][]}
8+
*/
9+
10+
var combinationSum = function(candidates, target) {
11+
const result = [];
12+
13+
const backtrack = (remaining, combo, start) => {
14+
if (remaining === 0) {
15+
result.push([...combo]);
16+
return;
17+
}
18+
19+
for (let i = start; i < candidates.length; i++) {
20+
if (candidates[i] <= remaining) {
21+
combo.push(candidates[i]);
22+
backtrack(remaining - candidates[i], combo, i);
23+
combo.pop();
24+
}
25+
}
26+
};
27+
28+
backtrack(target, [], 0);
29+
return result;
30+
};

combination-sum/HodaeSsi.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# 시간복잡도 : O(n * m) (n: target, m: len(candidates))
2+
# 공간복잡도 : O(n * m)
3+
class Solution:
4+
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
5+
dp = [[] for _ in range(target + 1)]
6+
dp[0] = [[]]
7+
8+
for candidate in candidates:
9+
for num in range(candidate, target + 1):
10+
for combination in dp[num - candidate]:
11+
temp = combination.copy()
12+
temp.extend([candidate])
13+
dp[num].append(temp)
14+
15+
return dp[target]
16+

combination-sum/Real-Reason.kt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package leetcode_study
2+
3+
fun combinationSum(candidates: IntArray, target: Int): List<List<Int>> {
4+
val result = mutableListOf<List<Int>>()
5+
val nums = ArrayDeque<Int>()
6+
dfs(candidates, target, 0, 0, nums, result)
7+
8+
return result
9+
}
10+
11+
private fun dfs(candidates: IntArray, target: Int, startIdx: Int, total: Int, nums: ArrayDeque<Int>, result: MutableList<List<Int>>) {
12+
if (target < total) return
13+
if (target == total) {
14+
result.add(ArrayList(nums))
15+
return
16+
}
17+
for (i in startIdx..< candidates.size) {
18+
val num = candidates[i]
19+
nums.add(num)
20+
dfs(candidates, target, i, total + num, nums, result)
21+
nums.removeLast()
22+
}
23+
}

combination-sum/Zioq.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* @param {number[]} candidates
3+
* @param {number} target
4+
* @return {number[][]}
5+
*/
6+
var combinationSum = function(candidates, target) {
7+
let result = [];
8+
9+
function find_combination(index, target, current) {
10+
if (target === 0) {
11+
result.push([...current]);
12+
return;
13+
}
14+
15+
for (let i = index; i < candidates.length; i++) {
16+
// Only proceed if current number doesn't exceed target
17+
if (candidates[i] <= target) {
18+
// Include current number in combination
19+
current.push(candidates[i]);
20+
21+
// Recursive call with:
22+
// - same index i (allowing reuse of same number)
23+
// - reduced target by current number
24+
find_combination(i, target - candidates[i], current);
25+
26+
// Backtrack: remove the last added number to try other combinations
27+
current.pop();
28+
}
29+
}
30+
}
31+
32+
find_combination(0, target, []);
33+
return result;
34+
};
35+
36+
/*
37+
38+
39+
40+
*/
41+
42+
console.log(combinationSum([2,3,6,7], 7))
43+
44+

combination-sum/donghyeon95.java

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import java.util.ArrayList;
2+
import java.util.Arrays;
3+
import java.util.Comparator;
4+
import java.util.HashMap;
5+
import java.util.HashSet;
6+
import java.util.List;
7+
import java.util.stream.Collectors;
8+
9+
class Solution {
10+
private HashMap<Integer, List<String>> dp = new HashMap<>();
11+
private HashSet<Integer> set;
12+
13+
public List<List<Integer>> combinationSum(int[] candidates, int target) {
14+
set = new HashSet<>(Arrays.stream(candidates).boxed().toList());
15+
recurse(target);
16+
// Convert dp entries back to List<List<Integer>> for return
17+
return dp.getOrDefault(target, new ArrayList<>()).stream()
18+
.map(str -> Arrays.stream(str.split(" "))
19+
.map(Integer::valueOf)
20+
.collect(Collectors.toList()))
21+
.collect(Collectors.toList());
22+
}
23+
24+
public void recurse(int target) {
25+
if (dp.containsKey(target)) return;
26+
27+
List<String> combinations = new ArrayList<>();
28+
for (int i = 1; i < target + 1; i++) {
29+
if (set.contains(i)) {
30+
int remaining = target - i;
31+
recurse(remaining);
32+
if (dp.containsKey(remaining)) {
33+
for (String combination : dp.get(remaining)) {
34+
List<Integer> newCombination = new ArrayList<>(Arrays.stream(combination.split(" "))
35+
.map(Integer::valueOf)
36+
.toList());
37+
newCombination.add(i);
38+
newCombination.sort(Comparator.reverseOrder());
39+
40+
String newCombinationStr = newCombination.stream()
41+
.map(String::valueOf)
42+
.collect(Collectors.joining(" "));
43+
if (!combinations.contains(newCombinationStr)) {
44+
combinations.add(newCombinationStr);
45+
}
46+
}
47+
}
48+
}
49+
}
50+
if (set.contains(target)) {
51+
String singleCombination = String.valueOf(target);
52+
if (!combinations.contains(singleCombination)) {
53+
combinations.add(singleCombination);
54+
}
55+
}
56+
dp.put(target, combinations);
57+
}
58+
59+
}
60+

combination-sum/dusunax.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
'''
2+
# 39. Combination Sum
3+
4+
Backtracking for find combinations.
5+
6+
## Time and Space Complexity
7+
8+
```
9+
TC: O(n^2)
10+
SC: O(n)
11+
```
12+
13+
#### TC is O(n^2):
14+
- iterating through the list in backtracking recursion to find combinations. = O(n^2)
15+
16+
#### SC is O(n):
17+
- using a list to store the combinations. = O(n)
18+
'''
19+
20+
class Solution:
21+
# Backtracking = find combination
22+
# candidate is distinct & can use multiple times.
23+
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
24+
result = []
25+
26+
def backtrack(currIdx, remain, combination):
27+
if(remain == 0):
28+
result.append(combination[:])
29+
return
30+
if(remain < 0):
31+
return
32+
33+
for i in range(currIdx, len(candidates)):
34+
combination.append(candidates[i])
35+
backtrack(i, remain - candidates[i], combination)
36+
combination.pop()
37+
38+
backtrack(0, target, [permutations])
39+
return result

0 commit comments

Comments
 (0)