Skip to content

Commit

Permalink
Merge branch 'DaleStudy:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
Chaedie authored Dec 31, 2024
2 parents 5f929c8 + 03ded85 commit 645e529
Show file tree
Hide file tree
Showing 155 changed files with 4,528 additions and 1 deletion.
53 changes: 53 additions & 0 deletions 3sum/Yjason-K.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/**
* 세 수의 합이 0이 되는 모든 고유한 조합을 찾는 함수
*
* @param {number[]} nums - 정수 배열
* @returns {number[][]} - 세 수의 합이 0이 되는 조합 배열
*
* 1. 입력 배열 `nums`를 오름차순으로 정렬.
* 2. 이중 반복문을 사용하여 각 요소를 기준으로 `투 포인터(two-pointer)`를 이용해 조합을 탐색.
* 3. 중복 조합을 방지하기 위해 `Set`을 사용하여 결과 조합의 문자열을 저장.
* 4. 조건에 맞는 조합을 `result` 배열에 추가합니다.
*
* 시간 복잡도:
* - 정렬: O(n log n)
* - 이중 반복문 및 투 포인터: O(n^2)
* - 전체 시간 복잡도: O(n^2)
*
* 공간 복잡도:
* - `Set` 및 `result` 배열에 저장되는 고유 조합: O(k), k는 고유한 조합의 수
* - 전체 공간 복잡도: O(n + k)
*/
function threeSum(nums: number[]): number[][] {
const sumSet = new Set<string>();
const result: number[][] = [];
nums.sort((a, b) => a - b);

// 첫 번째 요소를 기준으로 반복문 수행
for (let i = 0; i < nums.length - 2; i++) {
// 정렬 된 상태이기 때문에 시작점을 기준으로 다음 값 중복 비교
if (i > 0 && nums[i] === nums[i - 1]) continue;

let start = i + 1, end = nums.length - 1;
while (start < end) {
const sum = nums[i] + nums[start] + nums[end];
if (sum > 0) {
end--;
} else if (sum < 0) {
start++;
} else {
const triplet = [nums[i], nums[start], nums[end]];
const key = triplet.toString();
if (!sumSet.has(key)) {
sumSet.add(key);
result.push(triplet);
}
start++;
end--;
}
}
}

return result;
}

53 changes: 53 additions & 0 deletions binary-tree-level-order-traversal/Gotprgmer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/

// preorder에서 맨 왼쪽을 root
// root값을 기반으로 inorder에서 인덱스를 찾는다 그리고 왼쪽 오른쪽 길이를 구한다.
// 다시 buildTree 함수를 재귀하는데 이때 위에서 구한 왼쪽 길이와 오른쪽길이를 참고해서
// 왼쪽 buildTree
// value를 갱신
// 오른쪽 buildTree를 갱신한다.

// 시간복잡도 : O(N^2) -> 한쪽으로 치우친 트리일 경우 O(N)(index of) + T(N-1)이 될 수 있다.
// 위 식을 전개해보면 N + N-1 + N-2 + ... + 1 = N(N+1)/2 = O(N^2)
// 공간복잡도 : O(N) ->리트코드 but N길이의 리스트 크기*N번의 재귀호출이 일어날 수 있다. 따라서 O(N^2)가 아닌가...?
class SolutionGotprgmer {
public TreeNode buildTree(int[] preorder, int[] inorder) {

if(preorder.length == 0 || indexOf(inorder,preorder[0]) == -1){
return null;
}
TreeNode node = new TreeNode();

int root = preorder[0];
int indexOfRoot = indexOf(inorder,root);
int leftCnt = indexOfRoot;
// 찾으면
node.val = root;
node.left = buildTree(Arrays.copyOfRange(preorder,1,1+leftCnt),Arrays.copyOfRange(inorder,0,leftCnt));
node.right = buildTree(Arrays.copyOfRange(preorder,1+leftCnt,preorder.length),Arrays.copyOfRange(inorder,1+leftCnt,inorder.length));
return node;
}
public int indexOf(int[] intArray,int findNum){
for(int i=0;i<intArray.length;i++){
if(findNum==intArray[i]){
return i;
}
}
return -1;
}

}
43 changes: 43 additions & 0 deletions combination-sum/GangBean.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
/**
1. understanding
- find all combinations, which sum to target
- can use same number multiple times
2. strategy
- dp[target]: all combination, which sum to target
- dp[n + 1] = dp[n] | dp[1]
- [2,3,6,7], target = 7
- dp[0] = [[]]
- dp[1] = [[]]
- dp[2] = [[2]]
- dp[3] = [[3]]
- dp[4] = dp[2] | dp[2] = [[2,2]]
- dp[5] = dp[2] | dp[3] = [[2,3]]
- dp[6] = dp[2] | dp[4] , dp[3] | dp[3] = [[2,2,2], [3,3]]
- dp[7] = dp[2] | dp[5], dp[3] | dp[4], dp[6] | dp[1], dp[7] = [[2,2,3],]
3. complexity
- time: O(target * N) where N is length of candidates
- space: O(target * N)
*/
List<List<Integer>>[] dp = new List[target + 1];
for (int i = 0; i <= target; i++) {
dp[i] = new ArrayList<>();
}

dp[0].add(new ArrayList<>());

for (int candidate : candidates) {
for (int i = candidate; i <= target; i++) {
for (List<Integer> combination : dp[i - candidate]) {
List<Integer> newCombination = new ArrayList<>(combination);
newCombination.add(candidate);
dp[i].add(newCombination);
}
}
}

return dp[target];
}
}

30 changes: 30 additions & 0 deletions combination-sum/HerrineKim.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// 시간 복잡도 : O(n^2)
// 공간 복잡도 : O(n)

/**
* @param {number[]} candidates
* @param {number} target
* @return {number[][]}
*/

var combinationSum = function(candidates, target) {
const result = [];

const backtrack = (remaining, combo, start) => {
if (remaining === 0) {
result.push([...combo]);
return;
}

for (let i = start; i < candidates.length; i++) {
if (candidates[i] <= remaining) {
combo.push(candidates[i]);
backtrack(remaining - candidates[i], combo, i);
combo.pop();
}
}
};

backtrack(target, [], 0);
return result;
};
16 changes: 16 additions & 0 deletions combination-sum/HodaeSsi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# 시간복잡도 : O(n * m) (n: target, m: len(candidates))
# 공간복잡도 : O(n * m)
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
dp = [[] for _ in range(target + 1)]
dp[0] = [[]]

for candidate in candidates:
for num in range(candidate, target + 1):
for combination in dp[num - candidate]:
temp = combination.copy()
temp.extend([candidate])
dp[num].append(temp)

return dp[target]

23 changes: 23 additions & 0 deletions combination-sum/Real-Reason.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package leetcode_study

fun combinationSum(candidates: IntArray, target: Int): List<List<Int>> {
val result = mutableListOf<List<Int>>()
val nums = ArrayDeque<Int>()
dfs(candidates, target, 0, 0, nums, result)

return result
}

private fun dfs(candidates: IntArray, target: Int, startIdx: Int, total: Int, nums: ArrayDeque<Int>, result: MutableList<List<Int>>) {
if (target < total) return
if (target == total) {
result.add(ArrayList(nums))
return
}
for (i in startIdx..< candidates.size) {
val num = candidates[i]
nums.add(num)
dfs(candidates, target, i, total + num, nums, result)
nums.removeLast()
}
}
44 changes: 44 additions & 0 deletions combination-sum/Zioq.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* @param {number[]} candidates
* @param {number} target
* @return {number[][]}
*/
var combinationSum = function(candidates, target) {
let result = [];

function find_combination(index, target, current) {
if (target === 0) {
result.push([...current]);
return;
}

for (let i = index; i < candidates.length; i++) {
// Only proceed if current number doesn't exceed target
if (candidates[i] <= target) {
// Include current number in combination
current.push(candidates[i]);

// Recursive call with:
// - same index i (allowing reuse of same number)
// - reduced target by current number
find_combination(i, target - candidates[i], current);

// Backtrack: remove the last added number to try other combinations
current.pop();
}
}
}

find_combination(0, target, []);
return result;
};

/*
*/

console.log(combinationSum([2,3,6,7], 7))


60 changes: 60 additions & 0 deletions combination-sum/donghyeon95.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;

class Solution {
private HashMap<Integer, List<String>> dp = new HashMap<>();
private HashSet<Integer> set;

public List<List<Integer>> combinationSum(int[] candidates, int target) {
set = new HashSet<>(Arrays.stream(candidates).boxed().toList());
recurse(target);
// Convert dp entries back to List<List<Integer>> for return
return dp.getOrDefault(target, new ArrayList<>()).stream()
.map(str -> Arrays.stream(str.split(" "))
.map(Integer::valueOf)
.collect(Collectors.toList()))
.collect(Collectors.toList());
}

public void recurse(int target) {
if (dp.containsKey(target)) return;

List<String> combinations = new ArrayList<>();
for (int i = 1; i < target + 1; i++) {
if (set.contains(i)) {
int remaining = target - i;
recurse(remaining);
if (dp.containsKey(remaining)) {
for (String combination : dp.get(remaining)) {
List<Integer> newCombination = new ArrayList<>(Arrays.stream(combination.split(" "))
.map(Integer::valueOf)
.toList());
newCombination.add(i);
newCombination.sort(Comparator.reverseOrder());

String newCombinationStr = newCombination.stream()
.map(String::valueOf)
.collect(Collectors.joining(" "));
if (!combinations.contains(newCombinationStr)) {
combinations.add(newCombinationStr);
}
}
}
}
}
if (set.contains(target)) {
String singleCombination = String.valueOf(target);
if (!combinations.contains(singleCombination)) {
combinations.add(singleCombination);
}
}
dp.put(target, combinations);
}

}

39 changes: 39 additions & 0 deletions combination-sum/dusunax.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
'''
# 39. Combination Sum
Backtracking for find combinations.
## Time and Space Complexity
```
TC: O(n^2)
SC: O(n)
```
#### TC is O(n^2):
- iterating through the list in backtracking recursion to find combinations. = O(n^2)
#### SC is O(n):
- using a list to store the combinations. = O(n)
'''

class Solution:
# Backtracking = find combination
# candidate is distinct & can use multiple times.
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
result = []

def backtrack(currIdx, remain, combination):
if(remain == 0):
result.append(combination[:])
return
if(remain < 0):
return

for i in range(currIdx, len(candidates)):
combination.append(candidates[i])
backtrack(i, remain - candidates[i], combination)
combination.pop()

backtrack(0, target, [permutations])
return result
Loading

0 comments on commit 645e529

Please sign in to comment.