-
-
Notifications
You must be signed in to change notification settings - Fork 305
[rivkode] WEEK 02 solutions #2045
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| /* | ||
| 1. 문제분석 | ||
| 3개의 수를 더해서 0을 만들자 | ||
|
|
||
| 2. 예외 케이스 | ||
|
|
||
| 3. 알고리즘 | ||
| 2포인터 활용 | ||
|
|
||
| 4. 구현 | ||
|
|
||
| [-4, -1, -1, 0, 1, 2] | ||
|
|
||
| 배열을 정렬하고 2개의 포인터를 잡은 뒤 더한 값의 -한 값이 배열 내에 존재하는지 체크 | ||
| 배열의 i 값과 2개 포인터를 모두 더한 값이 음수라면 left를 우측으로 이동 | ||
| 배열의 i 값과 2개 포인터를 모두 더한 값이 양수라면 right를 좌측으로 이동 | ||
| */ | ||
|
|
||
| import java.util.*; | ||
|
|
||
| class Solution { | ||
| public List<List<Integer>> threeSum(int[] nums) { | ||
| Arrays.sort(nums); | ||
| Set<List<Integer>> set = new HashSet<>(); | ||
|
|
||
| for (int i=0; i<nums.length; i++) { | ||
| // target 변수 세팅 | ||
| int target = nums[i]; | ||
| int left = i+1; | ||
| int right = nums.length - 1; | ||
|
|
||
| // left, right 포인터 서로 이동 | ||
| while (left < right) { | ||
| int leftInt = nums[left]; | ||
| int rightInt = nums[right]; | ||
|
|
||
| if ((target + leftInt + rightInt) == 0) { | ||
| List<Integer> temp = new ArrayList<>(); | ||
| temp.add(target); | ||
| temp.add(leftInt); | ||
| temp.add(rightInt); | ||
|
|
||
| set.add(temp); | ||
|
|
||
| // 일치할 경우 해당 선택된 인덱스에 대해 추가로 확인하기 위해서 left, right 값 변경 | ||
| left += 1; | ||
| right -= 1; | ||
| } else if ((target + leftInt + rightInt) < 0) { | ||
| left += 1; | ||
| } else if ((target + leftInt + rightInt) > 0) { | ||
| right -= 1; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return set.stream().collect(Collectors.toList()); | ||
| } | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| /* | ||
| 이것도 dp 아닌가 ? | ||
| 이전의 계산들을 다음 계산에 사용할 수 있음 | ||
| 메모이제이션과 dp를 사용하면 풀 수 있을 것 같은데 | ||
| dp 아니네 | ||
|
|
||
| 만약 5를 만드려면 | ||
| 3을 만드는 경우의 수와 2를 만드는 경우의 수를 곱하면 되는것 아닌가 ? | ||
|
|
||
| 3을 만드려면 ? | ||
| 2를 만들 수 있는 경우의 수에 1을 만들 수 있는 경우의 수를 더해주면 되는거 아닌가 ? | ||
| 순서를 바꾸고 ? | ||
|
|
||
| 111 | ||
| 21 | ||
| 12 | ||
|
|
||
| 1111 | ||
| 211 | ||
| 121 | ||
| 112 | ||
| 22 | ||
|
|
||
| 11111 | ||
| 2111 | ||
| 1211 | ||
| 1121 | ||
| 1112 | ||
| 221 | ||
| 212 | ||
| 122 | ||
|
|
||
| 111111 | ||
| 21111 | ||
| 12111 | ||
| 11211 | ||
| 11121 | ||
| 11112 | ||
| 1122 | ||
| 1212 | ||
| 1221 | ||
| 2211 | ||
| 2121 | ||
| 2112 | ||
| 222 | ||
|
|
||
|
|
||
|
|
||
|
|
||
| 1 - 1 | ||
| 2 - 2 | ||
| 3 - 3 | ||
| 4 - 5 | ||
| 5 - 8 | ||
| 6 - 13 | ||
|
|
||
| count(3) = coun(1) + count(2) | ||
| count(4) = count(3) + count(2) | ||
|
|
||
| 점화식 | ||
|
|
||
| count(n) = count(n-1) + count(n-2) | ||
|
|
||
| */ | ||
|
|
||
| class Solution { | ||
| public int climbStairs(int n) { | ||
| // n은 45까지 있으므로 배열을 45까지 구하면 됨 | ||
|
|
||
| int[] arr = new int[45]; | ||
| arr[0] = 1; | ||
| arr[1] = 2; | ||
|
|
||
| for (int i=2; i<45; i++) { | ||
| arr[i] = arr[i-1] + arr[i-2]; | ||
| } | ||
|
|
||
| return arr[n-1]; | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,127 @@ | ||
| /** | ||
| * 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; | ||
| * } | ||
| * } | ||
| */ | ||
|
|
||
| /* | ||
| 1. 문제 이해 | ||
|
|
||
| 트리가 주어졌을 때 해당 트리가 BST인지 판별 | ||
| BST인제 판별하는 방법은 key 기준 left는 작아야 하고 right는 커야 한다. | ||
| 이 조건이 실패하면 해당 트리는 BST가 아니다. | ||
|
|
||
| 2. 예외 케이스 | ||
|
|
||
| 노드 개수의 범위는 | ||
| tree node가 1개부터 최고 1만개 까지 | ||
|
|
||
| 1개일 경우 | ||
| 바로 반환 | ||
|
|
||
| 그 외는 계산 진행 | ||
|
|
||
|
|
||
| 3. 알고리즘 선택 | ||
|
|
||
| dfs 선택 | ||
| a. 노드 key 기준으로 계속 파고들어서 반복할 수 있을 것 같아서 | ||
| b. left, right가 있는지를 기준으로 있다면 다시 dfs가 가능해서 | ||
|
|
||
| bfs로 해도 key를 알고 있으니까 되긴 할 것 같은데 일단 dfs로 해보자 | ||
|
|
||
| 아니다 bfs로 해야할 것 같은데 ? 이게 깊게 들어가는게 중요한게 아니라 전체 탐색을 해야하니 순차적으로 key들을 탐색하면서 작은지 큰지를 판별하면 될 것 같다. | ||
|
|
||
| bfs로 진행해보자 | ||
|
|
||
| 아니다 .. dfs가 맞네 하한 상한을 정해줘야 함 | ||
| 그리고 예외 케이스 있다 [-2147483648,null,2147483647] | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 엣지 케이스에 대해서도 분석하신 점이 인상깊습니다!! |
||
|
|
||
| 처음에 하한과 상한을 MIN_VALUE, MAX_VALUE를 통해 사용하고 있었는데 위 엣지 케이스를 발견 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저는 DFS로 이 문제에 접근할 때 상한/하한을 넣어줘야 하는 부분에서 헤맸었는데요, 대신 BST는 inorder 순회를 하면 오름차순 정렬이 된다는 점에 착안해서도 문제를 풀어보았습니다! 다른 풀이 방법도 슬쩍 공유드려요~! |
||
|
|
||
| 처음에는 Integer.MIN_VALUE 와 같이 Integer을 사용해서 위 예외 케이스를 만났는데 | ||
| 이걸 15분 동안 고민하다 gemini 한테 물어보니까 그냥 Long 쓰면 된단다 ... | ||
| Long으로 변경하니 통과 .. | ||
|
|
||
| 만약 조건범위가 Long 의 범위였다면 ,,? 어떻게 해결해야했을까. | ||
| 4. 구현 | ||
|
|
||
| */ | ||
|
|
||
| import java.util.*; | ||
|
|
||
| class Solution { | ||
| public boolean isValidBST(TreeNode root) { | ||
| Long min = Long.MIN_VALUE; | ||
| Long max = Long.MAX_VALUE; | ||
|
|
||
| if (root.left == null && root.right == null) { | ||
| return true; | ||
| } | ||
|
|
||
| return dfs(root, min, max); | ||
|
|
||
| } | ||
|
|
||
| public boolean dfs(TreeNode node, long min, long max) { | ||
| if (node == null) { | ||
| return true; | ||
| } | ||
|
|
||
| // 정상 범위 | ||
| if (min < node.val && node.val < max) { | ||
| return dfs(node.left, min, node.val) && dfs(node.right, node.val, max); | ||
| } else { | ||
| return false; | ||
| } | ||
| } | ||
|
|
||
| // 아래와 같이 풀려고 했으나 하한값과 상한값에 대한 인자를 넘겨줘야 하는데 넘겨줄 수 없어서 dfs로 풀어야 함 | ||
| // 에러 케이스 | ||
| // [5,4,6,null,null,3,7] | ||
| // private static int preKey; | ||
| // public boolean isValidBST(TreeNode root) { | ||
| // Queue<TreeNode> queue = new LinkedList<>(); | ||
|
|
||
| // queue.offer(root); | ||
| // preKey = root.val; | ||
|
|
||
| // while (!queue.isEmpty()) { | ||
| // TreeNode node = queue.poll(); | ||
| // int key = node.val; | ||
| // TreeNode left = node.left; | ||
| // TreeNode right = node.right; | ||
|
|
||
| // // left 처리 | ||
| // if (left != null) { | ||
| // queue.offer(left); | ||
| // if (left.val >= key) { | ||
| // return false; | ||
| // } | ||
|
|
||
| // if () | ||
| // } | ||
|
|
||
| // // right 처리 | ||
| // if (right != null) { | ||
| // queue.offer(right); | ||
| // if (right.val <= key) { | ||
| // return false; | ||
| // } | ||
| // } | ||
| // } | ||
|
|
||
| // return true; | ||
| // } | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이렇게 DP 테이블의 가장 최근 n개의 원소만 사용하는 경우에는 O(n) space의 DP 테이블 대신 O(1) space의 변수를 사용해서 공간 복잡도를 한 단계 최적화 할 수 있을 것 같아요~! (물론 이번 문제에서는 n <= 45 조건이 있기는 하지만요..!)