-
Notifications
You must be signed in to change notification settings - Fork 126
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'DaleStudy:main' into main
- Loading branch information
Showing
155 changed files
with
4,528 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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]; | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)) | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
|
||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Oops, something went wrong.