Skip to content

Commit 7222c35

Browse files
authoredFeb 22, 2025
Merge pull request #1042 from forest000014/main
[forest000014] Week 11
2 parents 6d14b8d + cd23cc2 commit 7222c35

File tree

9 files changed

+409
-0
lines changed

9 files changed

+409
-0
lines changed
 

‎3sum/forest000014.java

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
# Time Complexity: O(n^2)
3+
# Space Complexity: O(1)
4+
*/
5+
6+
class Solution {
7+
public List<List<Integer>> threeSum1(int[] nums) { // solution 1
8+
int n = nums.length;
9+
Arrays.sort(nums);
10+
Set<List<Integer>> ans = new HashSet<>();
11+
12+
for (int i = 0; i < n - 2; i++) {
13+
for (int j = i + 1; j < n - 1; j++) {
14+
int target = -nums[i] - nums[j]; // nums[i], nums[j]와 더해서 합이 0이 되기 위해 nums[k]가 가져야하는 값
15+
int k = -1;
16+
int l = j + 1;
17+
int r = n - 1;
18+
while (l <= r) {
19+
int m = (r - l) / 2 + l;
20+
if (nums[m] == target) {
21+
k = m;
22+
break;
23+
} else if (nums[m] < target) {
24+
l = m + 1;
25+
} else {
26+
r = m - 1;
27+
}
28+
}
29+
if (k != -1) { // binary search에서 target을 찾은 경우
30+
ans.add(new ArrayList<>(Arrays.asList(nums[i], nums[j], nums[k])));
31+
}
32+
}
33+
}
34+
35+
return new ArrayList<>(ans);
36+
}
37+
38+
public List<List<Integer>> threeSum(int[] nums) { // solution 2
39+
int n = nums.length;
40+
Arrays.sort(nums);
41+
Set<List<Integer>> ans = new HashSet<>();
42+
43+
for (int i = 0; i < n - 2; i++) {
44+
int l = i + 1;
45+
int r = n - 1;
46+
int target = -nums[i];
47+
while (l < r) {
48+
int sum = nums[l] + nums[r];
49+
if (sum == target) {
50+
ans.add(new ArrayList<>(Arrays.asList(nums[i], nums[l], nums[r])));
51+
l++;
52+
r--; // 또 다른 (l, r) 조합이 있을 수 있으므로, loop를 계속 이어간다.
53+
} else if (sum < target) {
54+
l++;
55+
} else {
56+
r--;
57+
}
58+
}
59+
}
60+
61+
return new ArrayList<>(ans);
62+
}
63+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
# Time Complexity: O(n)
3+
# Space Complexity: O(n)
4+
- 재귀 호출 내부에서 left, right 변수를 사용하고, 재귀 호출 최대 깊이는 n이므로
5+
# Solution
6+
전체 문제를 각 subtree에 대한 문제로 쪼개어 생각할 수 있습니다.
7+
임의의 노드 x에 대해, x의 왼쪽 자식을 x_l, x의 오른쪽 자식을 x_r, x의 값을 x.val이라고 정의하겠습니다.
8+
x를 root로 하는 subtree에서 'x를 path의 한쪽 끝으로 하는 path sum 중 최대값'을 dp[x]라고 정의하겠습니다.
9+
그러면 dp[x] = max(max(0, dp[x_l]) + x.val, max(0, dp[x_r]) + x.val) 로 구할 수 있습니다. (subtree의 dp 값이 음수인 경우는 버리면 되기 때문에.)
10+
이제 root로부터 출발해서 DFS로 전체 노드를 순회하며 이 점화식을 적용하면, 전체 tree에 대해 dp값을 구할 수 있습니다.
11+
단, 문제에서 원하는 답은 root를 반드시 path의 한쪽 끝으로 원하는 것은 아니고, 심지어 root가 path에 포함되지 않아도 되기 때문에,
12+
어중간한(?) (= root를 path에 포함하지 않는) path도 고려할 필요가 있는데요.
13+
이를 고려하기 위해, 각 재귀 함수 호출마다 max(0, dp[x_l]) + root.val + max(0, dp[x_r]) 값이 정답이 될 수 있는지 체크하는 과정이 필요합니다.
14+
*/
15+
/**
16+
* Definition for a binary tree node.
17+
* public class TreeNode {
18+
* int val;
19+
* TreeNode left;
20+
* TreeNode right;
21+
* TreeNode() {}
22+
* TreeNode(int val) { this.val = val; }
23+
* TreeNode(int val, TreeNode left, TreeNode right) {
24+
* this.val = val;
25+
* this.left = left;
26+
* this.right = right;
27+
* }
28+
* }
29+
*/
30+
class Solution {
31+
public int ans = -30_000_001;
32+
public int maxPathSum(TreeNode root) {
33+
maxInTree(root);
34+
35+
return ans;
36+
}
37+
38+
public int maxInTree(TreeNode root) {
39+
if (root == null) {
40+
return 0;
41+
}
42+
43+
int left = Math.max(0, maxInTree(root.left));
44+
int right = Math.max(0, maxInTree(root.right));
45+
46+
ans = Math.max(ans, left + root.val + right);
47+
48+
return root.val + Math.max(left, right);
49+
}
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
이 문제는 힌트의 도움을 받아서 풀었습니다.
3+
- preorder의 첫 원소는 항상 root node임
4+
- inorder에서 root node의 왼쪽의 원소들은 root node의 왼쪽 subtree, 오른쪽 원소들은 오른쪽 subtree임
5+
- 왼쪽 subtree와 오른쪽 subtree는 각각 preorder에서 연속하게 있음. (root, 왼쪽 subtree, 오른쪽 subtree 순)
6+
7+
시간 복잡도 : O(n)
8+
공간 복잡도 : O(n^2)
9+
(skewed tree의 경우, 최악의 공간 복잡도를 가짐)
10+
*/
11+
class Solution {
12+
public TreeNode buildTree(int[] preorder, int[] inorder) {
13+
if (preorder.length == 0) {
14+
return null;
15+
}
16+
if (preorder.length == 1) {
17+
return new TreeNode(preorder[0]);
18+
}
19+
int currIdx;
20+
for (currIdx = 0; currIdx < inorder.length; currIdx++) {
21+
if (inorder[currIdx] == preorder[0]) {
22+
break;
23+
}
24+
}
25+
26+
int[] lp = new int[currIdx];
27+
int[] li = new int[currIdx];
28+
int[] rp = new int[inorder.length - currIdx - 1];
29+
int[] ri = new int[inorder.length - currIdx - 1];
30+
for (int i = 0; i < currIdx; i++) {
31+
lp[i] = preorder[i + 1];
32+
li[i] = inorder[i];
33+
}
34+
for (int i = currIdx + 1; i < inorder.length; i++) {
35+
rp[i - currIdx - 1] = preorder[i];
36+
ri[i - currIdx - 1] = inorder[i];
37+
}
38+
39+
TreeNode lc = buildTree(lp, li);
40+
TreeNode rc = buildTree(rp, ri);
41+
42+
TreeNode curr = new TreeNode(preorder[0], lc, rc);
43+
44+
return curr;
45+
}
46+
}

‎decode-ways/forest000014.java

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
# Time Complexity: O(n)
3+
# Space Complexity: O(n)
4+
*/
5+
class Solution {
6+
7+
private boolean check12(char ch) {
8+
return (ch == '1' || ch == '2');
9+
}
10+
11+
private boolean check1(char ch) {
12+
return ch == '1';
13+
}
14+
15+
private boolean check2(char ch) {
16+
return ch == '2';
17+
}
18+
19+
private boolean check0(char ch) {
20+
return ch == '0';
21+
}
22+
23+
private boolean check6(char ch) {
24+
return ch <= '6';
25+
}
26+
27+
public int numDecodings(String s) {
28+
int n = s.length();
29+
30+
if (n == 0)
31+
return 0;
32+
33+
int[] dp = new int[n + 1];
34+
35+
if (check0(s.charAt(0)))
36+
return 0;
37+
38+
dp[0] = 1;
39+
dp[1] = 1;
40+
if (n == 1)
41+
return dp[1];
42+
43+
for (int i = 1; i < n; i++) {
44+
if (check0(s.charAt(i)) && !check12(s.charAt(i - 1)))
45+
return 0;
46+
47+
if (!check0(s.charAt(i)))
48+
dp[i + 1] = dp[i];
49+
50+
if (check1(s.charAt(i - 1)) || (check6(s.charAt(i)) && check2(s.charAt(i - 1))))
51+
dp[i + 1] += dp[i - 1];
52+
}
53+
return dp[n];
54+
}
55+
}

‎graph-valid-tree/forest000014.java

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
# Time Complexity: O(n)
3+
# Space Complexity: O(n + m)
4+
- m은 edges.length
5+
6+
# Solution
7+
edges[0][0]에서 출발하여 인접한 모든 edge를 DFS로 순회한다.
8+
- cycle이 있는 경우 (이미 방문한 적이 있는 node를 재방문)
9+
- 순회를 마쳤는데 방문하지 않은 node가 있는 경우
10+
위 2경우는 invalid tree이고, 그렇지 않으면 valid tree이다.
11+
*/
12+
class Solution {
13+
public ArrayList<ArrayList<Integer>> adj = new ArrayList<>();
14+
public boolean[] visited;
15+
public boolean validTree(int n, int[][] edges) {
16+
if (edges.length == 0) {
17+
return n == 1;
18+
}
19+
20+
visited = new boolean[n];
21+
22+
for (int i = 0; i < n; i++) {
23+
adj.add(new ArrayList<Integer>());
24+
}
25+
26+
for (int i = 0; i < edges.length; i++) {
27+
int a = edges[i][0];
28+
int b = edges[i][1];
29+
adj.get(a).add(b);
30+
adj.get(b).add(a);
31+
}
32+
33+
if (!dfs(-1, edges[0][0])) {
34+
return false;
35+
}
36+
37+
for (int i = 0; i < n; i++) {
38+
if (!visited[i]) {
39+
return false;
40+
}
41+
}
42+
43+
return true;
44+
}
45+
46+
public boolean dfs(int prev, int curr) {
47+
visited[curr] = true;
48+
49+
for (Integer next : adj.get(curr)) {
50+
if (next == prev) {
51+
continue;
52+
}
53+
54+
if (visited[next]) {
55+
return false;
56+
}
57+
58+
if (!dfs(curr, next)) {
59+
return false;
60+
}
61+
}
62+
63+
return true;
64+
}
65+
}

‎jump-game/forest000014.java

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
# Time Complexity: O(n)
3+
# Space Complexity: O(n)
4+
*/
5+
6+
class Solution {
7+
public boolean canJump(int[] nums) {
8+
int n = nums.length;
9+
boolean[] dp = new boolean[n];
10+
11+
dp[0] = true;
12+
13+
for (int i = 0; i < n; i++) {
14+
if (!dp[i]) return false;
15+
int j = Math.min(n - 1, i + nums[i]);
16+
for (; j >= i + 1; j--) {
17+
if (dp[j]) break;
18+
dp[j] = true;
19+
}
20+
}
21+
22+
return true;
23+
}
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
# Time Complexity: O(n)
3+
# Space Complexity: O(1)
4+
*/
5+
/**
6+
* Definition for a binary tree node.
7+
* public class TreeNode {
8+
* int val;
9+
* TreeNode left;
10+
* TreeNode right;
11+
* TreeNode() {}
12+
* TreeNode(int val) { this.val = val; }
13+
* TreeNode(int val, TreeNode left, TreeNode right) {
14+
* this.val = val;
15+
* this.left = left;
16+
* this.right = right;
17+
* }
18+
* }
19+
*/
20+
class Solution {
21+
public int maxDepth(TreeNode root) {
22+
if (root == null) {
23+
return 0;
24+
}
25+
26+
return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
27+
}
28+
}

‎merge-intervals/forest000014.java

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
# Time Complexity: O(nlogn)
3+
# Space Complexity: O(n)
4+
*/
5+
6+
class Solution {
7+
public int[][] merge(int[][] intervals) {
8+
int n = intervals.length;
9+
10+
Arrays.sort(intervals, (a, b) -> a[0] - b[0]);
11+
12+
ArrayList<int[]> ans = new ArrayList<>();
13+
ans.add(new int[2]);
14+
ans.get(0)[0] = intervals[0][0];
15+
ans.get(0)[1] = intervals[0][1];
16+
17+
for (int i = 1; i < n; i++) {
18+
if (ans.get(ans.size() - 1)[1] < intervals[i][0]) {
19+
ans.add(new int[2]);
20+
ans.get(ans.size() - 1)[0] = intervals[i][0];
21+
ans.get(ans.size() - 1)[1] = intervals[i][1];
22+
} else {
23+
ans.get(ans.size() - 1)[1] = Math.max(ans.get(ans.size() - 1)[1], intervals[i][1]);
24+
}
25+
}
26+
27+
return ans.toArray(new int[ans.size()][]);
28+
}
29+
}

‎reorder-list/forest000014.java

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
# Time Complexity: O(n)
3+
# Space Complexity: O(1)
4+
# Solution
5+
Dale 님의 솔루션을 참고했습니다.
6+
*/
7+
8+
/**
9+
* Definition for singly-linked list.
10+
* public class ListNode {
11+
* int val;
12+
* ListNode next;
13+
* ListNode() {}
14+
* ListNode(int val) { this.val = val; }
15+
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
16+
* }
17+
*/
18+
class Solution {
19+
public void reorderList(ListNode head) {
20+
ListNode slow = head;
21+
ListNode fast = head;
22+
while (fast != null && fast.next != null) {
23+
slow = slow.next;
24+
fast = fast.next.next;
25+
}
26+
27+
ListNode curr = slow.next;
28+
slow.next = null;
29+
30+
ListNode prev = null;
31+
while (curr != null) {
32+
ListNode tempNext = curr.next;
33+
curr.next = prev;
34+
prev = curr;
35+
curr = tempNext;
36+
}
37+
38+
ListNode left = head;
39+
ListNode right = prev;
40+
while (right != null) {
41+
ListNode leftNext = left.next;
42+
ListNode rightNext = right.next;
43+
left.next = right;
44+
right.next = leftNext;
45+
left = leftNext;
46+
right = rightNext;
47+
}
48+
}
49+
}

0 commit comments

Comments
 (0)
Please sign in to comment.