Skip to content

Commit c0ac47b

Browse files
committed
2 parents 629c125 + 2007a35 commit c0ac47b

File tree

18 files changed

+617
-0
lines changed

18 files changed

+617
-0
lines changed

3sum/GangBean.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
class Solution {
2+
public List<List<Integer>> threeSum(int[] nums) {
3+
/**
4+
1. understanding
5+
- integer array nums, find the whole combination of 3 nums, and the sum of the 3 nums equal to 0. And don't allow reusing same indiced number(but can duplicate in value)
6+
2. solve strategy
7+
- brute force
8+
- in every combination, validate sum of the nums equal to 0
9+
- but it can take O(N^3) times where N is the length of input array, and given that the N can be 3000 at most(3 * 10^3), time can be 27 * 10^9, which takes too long...
10+
- sort and two pointers
11+
- sort nums in ascending order, so move the left pointer to right means the sum of window is getting bigger.
12+
- and mid pointer set to left + 1 index
13+
- if sum of pointers is less than 0, then move mid pointer to right, until the sum is bigger than 0, and while processing them, if the sum of pointers is 0, then add the combination to the return list.
14+
- [-4, -1, -1, 0, 1, 2]:
15+
16+
3. complexity
17+
- time: O(N^2) -> each left pointer, you can search at most N-1, and left pointer's range is [0, N-1), so the max length is N-1 for left index pointer.
18+
- space: O(1) -> no extra space is needed
19+
*/
20+
// 0. assign return variable Set
21+
Set<List<Integer>> answer = new HashSet<>();
22+
23+
// 1. sort the num array in ascending order
24+
Arrays.sort(nums); // O(NlogN)
25+
// Arrays.stream(nums).forEach(System.out::println);
26+
27+
// 3. move the mid pointer from left to right to find the combination of which's sum is 0, and if the sum is over 0, and then move right pointer to the left. else if the sum is under 0, then move left pointer to right direction.
28+
for (int left = 0; left < nums.length - 1; left++) {
29+
int mid = left + 1;
30+
int right = nums.length - 1;
31+
while (mid < right) {
32+
// System.out.println(String.format("%d,%d,%d", nums[left], nums[mid], nums[right]));
33+
int sum = nums[left] + nums[mid] + nums[right];
34+
if (sum > 0) {
35+
right--;
36+
} else if (sum == 0) {
37+
answer.add(List.of(nums[left], nums[mid], nums[right]));
38+
right--;
39+
} else {
40+
mid++;
41+
}
42+
}
43+
}
44+
45+
return new ArrayList<>(answer);
46+
}
47+
}
48+

3sum/dalpang81.java

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* 시간복잡도 : O(N^2)
3+
* 공간복잡도 : O(1)
4+
* */
5+
import java.util.*;
6+
7+
class Solution {
8+
public List<List<Integer>> threeSum(int[] nums) {
9+
List<List<Integer>> result = new ArrayList<>();
10+
Arrays.sort(nums);
11+
12+
for (int i = 0; i < nums.length - 2; i++) {
13+
if (i > 0 && nums[i] == nums[i - 1]) {
14+
continue;
15+
}
16+
17+
int left = i + 1;
18+
int right = nums.length - 1;
19+
20+
while (left < right) {
21+
int sum = nums[i] + nums[left] + nums[right];
22+
23+
if (sum == 0)
24+
{
25+
// 합이 0인 경우 결과에 추가
26+
result.add(Arrays.asList(nums[i], nums[left], nums[right]));
27+
28+
// 중복된 값 건너뛰기
29+
while (left < right && nums[left] == nums[left + 1])
30+
left++;
31+
32+
while (left < right && nums[right] == nums[right - 1])
33+
right--;
34+
35+
left++;
36+
right--;
37+
}
38+
else if (sum < 0)
39+
left++;
40+
else
41+
right--;
42+
43+
}
44+
}
45+
return result;
46+
}
47+
}

3sum/easyone-jwlee.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// 풀이
2+
// 배열을 정렬하고
3+
// two pointer 사용
4+
5+
// TC
6+
// 정렬 O(nlogn) + Two pointer 이중 루프 O(n^2) = O(n^2)
7+
8+
// SC
9+
// Go의 sort.Ints()는 TimSort를 사용.
10+
// Merge Sort와 Insertion Sort의 조합으로 동작.
11+
// 정렬 O(n) + Two pointer O(1) + 결과 배열 O(n) = O(n)
12+
13+
func threeSum(nums []int) [][]int {
14+
result := [][]int{}
15+
sort.Ints(nums) // nums를 정렬
16+
17+
for i := 0; i < len(nums)-2; i++ {
18+
if i > 0 && nums[i] == nums[i-1] {
19+
continue // 중복된 값 건너뜀
20+
}
21+
22+
left, right := i+1, len(nums)-1
23+
for left < right {
24+
sum := nums[i] + nums[left] + nums[right]
25+
if sum == 0 {
26+
result = append(result, []int{nums[i], nums[left], nums[right]})
27+
left++
28+
right--
29+
30+
// 중복 제거
31+
for left < right && nums[left] == nums[left-1] {
32+
left++
33+
}
34+
for left < right && nums[right] == nums[right+1] {
35+
right--
36+
}
37+
} else if sum < 0 {
38+
left++
39+
} else {
40+
right--
41+
}
42+
}
43+
}
44+
45+
return result
46+
}

3sum/heypaprika.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# 2Sum을 활용한 풀이
2+
# Note : 정렬 후 푸는 것이 더 직관적이고, 빠름
3+
4+
"""
5+
복잡도 : 예상 -> 예상한 이유
6+
7+
시간 복잡도 : O(n^2) -> nums 배열 2중 for문
8+
공간 복잡도 : O(n) -> 최악의 경우 nums 배열 길이만큼의 딕셔너리 생성
9+
"""
10+
class Solution:
11+
def threeSum(self, nums: List[int]) -> List[List[int]]:
12+
ans_list = set()
13+
added_pair = {}
14+
for target_i, target_number in enumerate(nums):
15+
cur_ans_list = []
16+
num_dict = {}
17+
if target_number in added_pair:
18+
continue
19+
20+
for i in range(target_i + 1, len(nums)):
21+
num_A = nums[i]
22+
num_B = - target_number - num_A
23+
if num_B in num_dict:
24+
cur_ans_list.append(sorted([target_number, num_A, num_B]))
25+
added_pair[target_number] = num_A
26+
num_dict[num_A] = 1
27+
for item in cur_ans_list:
28+
ans_list.add(tuple(item))
29+
return list(ans_list)
30+

climbing-stairs/GangBean.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
class Solution {
2+
public int climbStairs(int n) {
3+
/**
4+
1. Understanding
5+
- return the count of ways to climb up to top
6+
- way means the sequence of step count
7+
- each state, there can be 2 ways. first climb 1 step, second climb 2 step
8+
2. solve strategy
9+
- assume the count of ways to climb up to K th stairs is C[K].
10+
- then, C[0] = 1, C[1] = 1, C[2] = 2(because, you can up to 2nd stair from 0th stair and also from 1st stair.)
11+
- and C[3] = C[2] + C[1], C[4] = C[3] + C[2], ... etc...
12+
- so we can fomulate C[k] = C[k-1] + C[k-2]
13+
- iterate over 0 to n, you can caculate C[k].
14+
- and finally return C[n] is the answer.
15+
16+
3. complexity
17+
- I answer to this part, along with coding upon each line description.
18+
*/
19+
20+
// 1. create array to demonstrate each stairs way count to reach that position.
21+
// the maximun step count is 45, so maybe there is over 2^32(approximately 2 billion; so i worry about the overflow), I assign long type array. Oh.. but i catch that return type of this method is integer, so i can assume that maximum value is under integer range. So, assign as integer.
22+
int[] c = new int[n + 1]; // the extra plus 1 means 0th stair state
23+
// space complexity: O(n)
24+
for (int stair = 0; stair <= n; stair++) { // time complexity O(n)
25+
if (stair <= 1) {
26+
c[stair] = 1; // O(1)
27+
continue;
28+
}
29+
c[stair] = c[stair-1] + c[stair-2]; // O(1)
30+
}
31+
32+
return c[n];
33+
}
34+
}
35+

climbing-stairs/dalpang81.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
시간복잡도 : O(n)
3+
공간복잡도 : O(n)
4+
*/
5+
class Solution {
6+
public int climbStairs(int n) {
7+
if (n <= 2) return n;
8+
9+
int[] dp = new int[n + 1];
10+
dp[1] = 1;
11+
dp[2] = 2;
12+
13+
for(int i = 3; i <= n; i++)
14+
dp[i] = dp[i - 1] + dp[i - 2];
15+
16+
return dp[n];
17+
18+
}
19+
}

climbing-stairs/easyone-jwlee.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// 풀이
2+
// 1 일 때, 가능한 step은 1 -> 1가지
3+
// 2 일 때, 가능한 step은 1 1, 2 -> 2가지
4+
// 3 일 때, 가능한 step은 1 1 1, 1 2, 2 1 -> 3가지
5+
// n 일 때, 가능한 stop은 n-1의 가짓수에 1이 붙고, n-2의 가짓수에 2가 붙는다.
6+
7+
// TC
8+
// O(n)
9+
10+
// SC
11+
// int타입 변수만 사용해서 O(1)
12+
13+
func climbStairs(n int) int {
14+
if n <= 2 {
15+
return n
16+
}
17+
prev := 1 // climb1
18+
curr := 2 // climb2
19+
for i := 3; i <= n; i++ {
20+
prev, curr = curr, (curr + prev)
21+
}
22+
return curr
23+
}

climbing-stairs/heypaprika.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
"""
2+
복잡도 : 예상 -> 예상한 이유
3+
4+
시간 복잡도 : O(n) -> 배열의 길이 n-2 만큼 반복하므로
5+
공간 복잡도 : O(n) -> n 길이의 배열 하나를 생성하므로
6+
"""
7+
class Solution:
8+
def climbStairs(self, n: int) -> int:
9+
if n == 1:
10+
return 1
11+
elif n == 2:
12+
return 2
13+
a = [0] * n
14+
a[0] = 1
15+
a[1] = 2
16+
for i in range(2, n):
17+
a[i] = a[i-1] + a[i-2]
18+
return a[n-1]
19+
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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+
class Solution {
17+
public TreeNode buildTree(int[] preorder, int[] inorder) {
18+
/**
19+
1. understanding
20+
- preorder: mid -> left -> right
21+
- inorder: left -> mid -> right
22+
- so, first element of the preorder array is always mid node.
23+
- if the idx of inorder's 1st depth mid node is k, then inorder[0:k-1] is the left tree part array. And also, preorder[k:] is the right tree part.
24+
2. strategy
25+
- find the inorder's mid node idx, and then split left tree part and right part, buildTree with each preorder and inorder part.
26+
27+
3. complexity
28+
- time: O(N^2)
29+
- space: O(N^2)
30+
*/
31+
if (preorder.length == 0) return null;
32+
if (preorder.length == 1) return new TreeNode(preorder[0]);
33+
int i = 0;
34+
List<Integer> leftPreorder = new ArrayList<>(); // O(N)
35+
List<Integer> leftInorder = new ArrayList<>(); // O(N)
36+
List<Integer> rightPreorder = new ArrayList<>(); // O(N)
37+
List<Integer> rightInorder = new ArrayList<>(); // O(N)
38+
for (; i < inorder.length; i++) { // O(N)
39+
if (inorder[i] == preorder[0]) break;
40+
leftPreorder.add(preorder[i+1]);
41+
leftInorder.add(inorder[i]);
42+
}
43+
for (int idx = i+1; idx < inorder.length; idx++) { // O(N)
44+
rightPreorder.add(preorder[idx]);
45+
rightInorder.add(inorder[idx]);
46+
}
47+
48+
return new TreeNode(preorder[0], buildTree(leftPreorder.stream().mapToInt(Integer::intValue).toArray(), leftInorder.stream().mapToInt(Integer::intValue).toArray()), buildTree(rightPreorder.stream().mapToInt(Integer::intValue).toArray(), rightInorder.stream().mapToInt(Integer::intValue).toArray()));
49+
}
50+
}
51+
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// 풀이
2+
// preorder[0]이 제일 꼭대기
3+
// preorder 배열의 root index, inorder 배열의 시작, inorder 배열의 끝
4+
// 위의 세가지를 parameter로 받는 재귀함수를 만들어서
5+
// 왼쪽 서브트리, 오른쪽 서브트리를 순회
6+
7+
// TC
8+
// map 만들기 O(n) + 재귀함수는 각 노드를 딱 한번씩만 방문하므로 O(n) = O(n)
9+
10+
// SC
11+
// map O(n) + 재귀함수 최악의 경우 한쪽으로만 노드가 이어지는 경우 O(n) = O(n)
12+
13+
func buildTree(preorder []int, inorder []int) *TreeNode {
14+
inorderMap := make(map[int]int)
15+
for i, n := range inorder {
16+
inorderMap[n] = i
17+
}
18+
19+
var recursive func(rootIndex, inStart, inEnd int) *TreeNode
20+
recursive = func(rootIndex, inStart, inEnd int) *TreeNode {
21+
if rootIndex >= len(preorder) || inStart > inEnd {
22+
return nil
23+
}
24+
rootVal := preorder[rootIndex]
25+
rootInorderIndex := inorderMap[rootVal]
26+
27+
result := &TreeNode{
28+
Val: rootVal,
29+
}
30+
31+
leftSize := rootInorderIndex - inStart
32+
33+
result.Left = recursive(rootIndex+1, inStart, rootInorderIndex-1)
34+
result.Right = recursive(rootIndex+1+leftSize, rootInorderIndex+1, inEnd)
35+
36+
return result
37+
}
38+
39+
return recursive(0, 0, len(inorder)-1)
40+
}

0 commit comments

Comments
 (0)