Skip to content

Commit

Permalink
Merge pull request DaleStudy#1042 from forest000014/main
Browse files Browse the repository at this point in the history
[forest000014] Week 11
  • Loading branch information
TonyKim9401 authored Feb 22, 2025
2 parents 6d14b8d + cd23cc2 commit 7222c35
Show file tree
Hide file tree
Showing 9 changed files with 409 additions and 0 deletions.
63 changes: 63 additions & 0 deletions 3sum/forest000014.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
# Time Complexity: O(n^2)
# Space Complexity: O(1)
*/

class Solution {
public List<List<Integer>> threeSum1(int[] nums) { // solution 1
int n = nums.length;
Arrays.sort(nums);
Set<List<Integer>> ans = new HashSet<>();

for (int i = 0; i < n - 2; i++) {
for (int j = i + 1; j < n - 1; j++) {
int target = -nums[i] - nums[j]; // nums[i], nums[j]와 더해서 합이 0이 되기 위해 nums[k]가 가져야하는 값
int k = -1;
int l = j + 1;
int r = n - 1;
while (l <= r) {
int m = (r - l) / 2 + l;
if (nums[m] == target) {
k = m;
break;
} else if (nums[m] < target) {
l = m + 1;
} else {
r = m - 1;
}
}
if (k != -1) { // binary search에서 target을 찾은 경우
ans.add(new ArrayList<>(Arrays.asList(nums[i], nums[j], nums[k])));
}
}
}

return new ArrayList<>(ans);
}

public List<List<Integer>> threeSum(int[] nums) { // solution 2
int n = nums.length;
Arrays.sort(nums);
Set<List<Integer>> ans = new HashSet<>();

for (int i = 0; i < n - 2; i++) {
int l = i + 1;
int r = n - 1;
int target = -nums[i];
while (l < r) {
int sum = nums[l] + nums[r];
if (sum == target) {
ans.add(new ArrayList<>(Arrays.asList(nums[i], nums[l], nums[r])));
l++;
r--; // 또 다른 (l, r) 조합이 있을 수 있으므로, loop를 계속 이어간다.
} else if (sum < target) {
l++;
} else {
r--;
}
}
}

return new ArrayList<>(ans);
}
}
50 changes: 50 additions & 0 deletions binary-tree-maximum-path-sum/forest000014.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
# Time Complexity: O(n)
# Space Complexity: O(n)
- 재귀 호출 내부에서 left, right 변수를 사용하고, 재귀 호출 최대 깊이는 n이므로
# Solution
전체 문제를 각 subtree에 대한 문제로 쪼개어 생각할 수 있습니다.
임의의 노드 x에 대해, x의 왼쪽 자식을 x_l, x의 오른쪽 자식을 x_r, x의 값을 x.val이라고 정의하겠습니다.
x를 root로 하는 subtree에서 'x를 path의 한쪽 끝으로 하는 path sum 중 최대값'을 dp[x]라고 정의하겠습니다.
그러면 dp[x] = max(max(0, dp[x_l]) + x.val, max(0, dp[x_r]) + x.val) 로 구할 수 있습니다. (subtree의 dp 값이 음수인 경우는 버리면 되기 때문에.)
이제 root로부터 출발해서 DFS로 전체 노드를 순회하며 이 점화식을 적용하면, 전체 tree에 대해 dp값을 구할 수 있습니다.
단, 문제에서 원하는 답은 root를 반드시 path의 한쪽 끝으로 원하는 것은 아니고, 심지어 root가 path에 포함되지 않아도 되기 때문에,
어중간한(?) (= root를 path에 포함하지 않는) path도 고려할 필요가 있는데요.
이를 고려하기 위해, 각 재귀 함수 호출마다 max(0, dp[x_l]) + root.val + max(0, dp[x_r]) 값이 정답이 될 수 있는지 체크하는 과정이 필요합니다.
*/
/**
* 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;
* }
* }
*/
class Solution {
public int ans = -30_000_001;
public int maxPathSum(TreeNode root) {
maxInTree(root);

return ans;
}

public int maxInTree(TreeNode root) {
if (root == null) {
return 0;
}

int left = Math.max(0, maxInTree(root.left));
int right = Math.max(0, maxInTree(root.right));

ans = Math.max(ans, left + root.val + right);

return root.val + Math.max(left, right);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
이 문제는 힌트의 도움을 받아서 풀었습니다.
- preorder의 첫 원소는 항상 root node임
- inorder에서 root node의 왼쪽의 원소들은 root node의 왼쪽 subtree, 오른쪽 원소들은 오른쪽 subtree임
- 왼쪽 subtree와 오른쪽 subtree는 각각 preorder에서 연속하게 있음. (root, 왼쪽 subtree, 오른쪽 subtree 순)
시간 복잡도 : O(n)
공간 복잡도 : O(n^2)
(skewed tree의 경우, 최악의 공간 복잡도를 가짐)
*/
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
if (preorder.length == 0) {
return null;
}
if (preorder.length == 1) {
return new TreeNode(preorder[0]);
}
int currIdx;
for (currIdx = 0; currIdx < inorder.length; currIdx++) {
if (inorder[currIdx] == preorder[0]) {
break;
}
}

int[] lp = new int[currIdx];
int[] li = new int[currIdx];
int[] rp = new int[inorder.length - currIdx - 1];
int[] ri = new int[inorder.length - currIdx - 1];
for (int i = 0; i < currIdx; i++) {
lp[i] = preorder[i + 1];
li[i] = inorder[i];
}
for (int i = currIdx + 1; i < inorder.length; i++) {
rp[i - currIdx - 1] = preorder[i];
ri[i - currIdx - 1] = inorder[i];
}

TreeNode lc = buildTree(lp, li);
TreeNode rc = buildTree(rp, ri);

TreeNode curr = new TreeNode(preorder[0], lc, rc);

return curr;
}
}
55 changes: 55 additions & 0 deletions decode-ways/forest000014.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
# Time Complexity: O(n)
# Space Complexity: O(n)
*/
class Solution {

private boolean check12(char ch) {
return (ch == '1' || ch == '2');
}

private boolean check1(char ch) {
return ch == '1';
}

private boolean check2(char ch) {
return ch == '2';
}

private boolean check0(char ch) {
return ch == '0';
}

private boolean check6(char ch) {
return ch <= '6';
}

public int numDecodings(String s) {
int n = s.length();

if (n == 0)
return 0;

int[] dp = new int[n + 1];

if (check0(s.charAt(0)))
return 0;

dp[0] = 1;
dp[1] = 1;
if (n == 1)
return dp[1];

for (int i = 1; i < n; i++) {
if (check0(s.charAt(i)) && !check12(s.charAt(i - 1)))
return 0;

if (!check0(s.charAt(i)))
dp[i + 1] = dp[i];

if (check1(s.charAt(i - 1)) || (check6(s.charAt(i)) && check2(s.charAt(i - 1))))
dp[i + 1] += dp[i - 1];
}
return dp[n];
}
}
65 changes: 65 additions & 0 deletions graph-valid-tree/forest000014.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
# Time Complexity: O(n)
# Space Complexity: O(n + m)
- m은 edges.length
# Solution
edges[0][0]에서 출발하여 인접한 모든 edge를 DFS로 순회한다.
- cycle이 있는 경우 (이미 방문한 적이 있는 node를 재방문)
- 순회를 마쳤는데 방문하지 않은 node가 있는 경우
위 2경우는 invalid tree이고, 그렇지 않으면 valid tree이다.
*/
class Solution {
public ArrayList<ArrayList<Integer>> adj = new ArrayList<>();
public boolean[] visited;
public boolean validTree(int n, int[][] edges) {
if (edges.length == 0) {
return n == 1;
}

visited = new boolean[n];

for (int i = 0; i < n; i++) {
adj.add(new ArrayList<Integer>());
}

for (int i = 0; i < edges.length; i++) {
int a = edges[i][0];
int b = edges[i][1];
adj.get(a).add(b);
adj.get(b).add(a);
}

if (!dfs(-1, edges[0][0])) {
return false;
}

for (int i = 0; i < n; i++) {
if (!visited[i]) {
return false;
}
}

return true;
}

public boolean dfs(int prev, int curr) {
visited[curr] = true;

for (Integer next : adj.get(curr)) {
if (next == prev) {
continue;
}

if (visited[next]) {
return false;
}

if (!dfs(curr, next)) {
return false;
}
}

return true;
}
}
24 changes: 24 additions & 0 deletions jump-game/forest000014.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
# Time Complexity: O(n)
# Space Complexity: O(n)
*/

class Solution {
public boolean canJump(int[] nums) {
int n = nums.length;
boolean[] dp = new boolean[n];

dp[0] = true;

for (int i = 0; i < n; i++) {
if (!dp[i]) return false;
int j = Math.min(n - 1, i + nums[i]);
for (; j >= i + 1; j--) {
if (dp[j]) break;
dp[j] = true;
}
}

return true;
}
}
28 changes: 28 additions & 0 deletions maximum-depth-of-binary-tree/forest000014.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
# Time Complexity: O(n)
# Space Complexity: O(1)
*/
/**
* 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;
* }
* }
*/
class Solution {
public int maxDepth(TreeNode root) {
if (root == null) {
return 0;
}

return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
}
}
29 changes: 29 additions & 0 deletions merge-intervals/forest000014.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
# Time Complexity: O(nlogn)
# Space Complexity: O(n)
*/

class Solution {
public int[][] merge(int[][] intervals) {
int n = intervals.length;

Arrays.sort(intervals, (a, b) -> a[0] - b[0]);

ArrayList<int[]> ans = new ArrayList<>();
ans.add(new int[2]);
ans.get(0)[0] = intervals[0][0];
ans.get(0)[1] = intervals[0][1];

for (int i = 1; i < n; i++) {
if (ans.get(ans.size() - 1)[1] < intervals[i][0]) {
ans.add(new int[2]);
ans.get(ans.size() - 1)[0] = intervals[i][0];
ans.get(ans.size() - 1)[1] = intervals[i][1];
} else {
ans.get(ans.size() - 1)[1] = Math.max(ans.get(ans.size() - 1)[1], intervals[i][1]);
}
}

return ans.toArray(new int[ans.size()][]);
}
}
Loading

0 comments on commit 7222c35

Please sign in to comment.