-
-
Notifications
You must be signed in to change notification settings - Fork 361
[dahyeong-yun] WEEK 02 solutions #2684
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
base: main
Are you sure you want to change the base?
Changes from all commits
16e9a46
2d2fa8b
e3cb2f5
967ef0c
2a15bb4
e0e4aef
e91932e
50214e7
90395d3
22934f6
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,53 @@ | ||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||
| * 0. 풀이 개요 | ||||||||||||||||||||||||||||||||||||||||||
| * - 시간복잡도 : O(n^2) | ||||||||||||||||||||||||||||||||||||||||||
| * - 공간복잡도 : O(1) | ||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| class Solution { | ||||||||||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||||||||||
| * 1. 풀이 과정 | ||||||||||||||||||||||||||||||||||||||||||
| * 1.1 문제 이해 | ||||||||||||||||||||||||||||||||||||||||||
| * - 세 수의 합이 0이 되는 중복 없는 전체 조합 찾기 | ||||||||||||||||||||||||||||||||||||||||||
| * 1.2 제약 사항 | ||||||||||||||||||||||||||||||||||||||||||
| * - 인덱스의 조합이 아닌 값의 조합이므로 배열의 원본을 유지할 필요는 없음 | ||||||||||||||||||||||||||||||||||||||||||
| * - 조합의 중복을 어떻게 제외 시킬지가 관건 | ||||||||||||||||||||||||||||||||||||||||||
| * 1.3 풀이 아이디어 | ||||||||||||||||||||||||||||||||||||||||||
| * - 하나의 값이 고정되어 있으면 나머지 두 원소의 합이 고정값 * -1 이 되어야 하는 형태라고도 볼 수 있음 | ||||||||||||||||||||||||||||||||||||||||||
| * - 배열의 인덱스는 몰라도 되므로 배열을 오름차순으로 정렬할 수 있음 | ||||||||||||||||||||||||||||||||||||||||||
| * - 이때 고정값 하나는 반복문 안에서 루프를 돌면서 정하고, 나머지 두 수는 투 포인터로 원하는 조합을 찾을 수 있음 | ||||||||||||||||||||||||||||||||||||||||||
| * - 배열이 오름차순으로 정렬되어 있으므로, 만약 합이 0 보다 크다면 숫자가 작아져야 하고, 0보다 작다면 숫자가 커져야 함. | ||||||||||||||||||||||||||||||||||||||||||
| * - 따라서 세 수의 합이 작아져야 한다면 우측 포인터를 좌측으로 옮기면서 숫자를 줄일 수 있고, | ||||||||||||||||||||||||||||||||||||||||||
| * - 합이 커져야 한다면 좌측 포인터를 우측으로 옮기면서 전체 합을 키울 수 있음. | ||||||||||||||||||||||||||||||||||||||||||
| * - 여기에 더해 중복을 제외하기 위해서 같은 수의 경우는 포인터를 건너뛰는 식으로 처리할 수 있음. | ||||||||||||||||||||||||||||||||||||||||||
| * - 시간복잡도는 배열의 원소(n)만큼 루프를 돌면서, 그 안에서 최악의 경우 n - 2 번 순회 하게 되므로 N(N-2) 가 되어 n^2 이라 볼 수 있음. | ||||||||||||||||||||||||||||||||||||||||||
| * - 추가적인 공간을 일부 만들기는 하는데 n에 차수에 대응하는 수가 없으므로 공간복잡도는 O(1)로 판단. | ||||||||||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||||||||||
| public List<List<Integer>> threeSum(int[] nums) { | ||||||||||||||||||||||||||||||||||||||||||
| Arrays.sort(nums); | ||||||||||||||||||||||||||||||||||||||||||
| List<List<Integer>> answer = new ArrayList<>(); | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| for(int i=0; i < nums.length - 2; i++) { | ||||||||||||||||||||||||||||||||||||||||||
| if (i > 0 && nums[i] == nums[i - 1]) { | ||||||||||||||||||||||||||||||||||||||||||
| continue; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+30
to
+34
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. nums[i] > 0 인 부분부터는
Contributor
Author
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.
Suggested change
이런 식으로 조기 종료를 할 수 있겠네요 |
||||||||||||||||||||||||||||||||||||||||||
| int left = i+1; | ||||||||||||||||||||||||||||||||||||||||||
| int right = nums.length - 1; | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| while(left < right) { | ||||||||||||||||||||||||||||||||||||||||||
| if(nums[i] + nums[left] + nums[right] == 0) { | ||||||||||||||||||||||||||||||||||||||||||
| List<Integer> triple = List.of(nums[i], nums[left], nums[right]); | ||||||||||||||||||||||||||||||||||||||||||
| answer.add(triple); | ||||||||||||||||||||||||||||||||||||||||||
| while(left+1 < right && nums[left] == nums[left+1]) left++; | ||||||||||||||||||||||||||||||||||||||||||
| while(right > 0 && nums[right] == nums[right-1]) right--; | ||||||||||||||||||||||||||||||||||||||||||
| left++; | ||||||||||||||||||||||||||||||||||||||||||
| right--; | ||||||||||||||||||||||||||||||||||||||||||
| } else if(nums[i] + nums[left] + nums[right] > 0) right--; | ||||||||||||||||||||||||||||||||||||||||||
| else left++; | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+38
to
+47
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. while(
Contributor
Author
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.
Suggested change
좌측 포인터가 우측을 넘어가지 않는 선에서 끝내려는 거니, 해당 조건을 공통으로 넣는 식으로 가독성을 개선할 수 있을 것 같네요. |
||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| return answer; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
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. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: 초기 경계조건을 명확히 두고 순차적으로 채워 나가는 DP 풀이입니다. 개선 제안: 메모리 사용을 줄이려면 두 변수로 롤링 배열로 구현하는 대안을 고려해볼 수 있습니다. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| /** | ||
| * 0. 풀이 개요 | ||
| * - 시간복잡도 : O(n) | ||
| * - 공간복잡도 : O(n) | ||
| */ | ||
| class Solution { | ||
| /** | ||
| * 1. 풀이 과정 | ||
| * 1.1 이해 | ||
| * - n 이 계단 수고 그 계단을 오르는 방법의 가짓 수를 | ||
| * 1.2 제약 | ||
| * - n이 1부터 45까지 임. | ||
| * 1.3 아이디어 | ||
| * - 전형적인 DP 로 보이긴 함. | ||
| * - 현 단계로 오기 위해서는 전 단계에서 + 1을 하던지 전전단계에서 + 2 하던지 하는 방법이 있음 | ||
| * - 즉 전 단계 까지의 가짓 수 + 전전 단계까지의 가짓 수 = 현 단계의 가짓 수 됨 | ||
| * - 1번째와 2번째는 전전 단계가 없으므로 직접 계산 해준다. | ||
| * - n까지 순회하면서 계산하며, 각 단계의 가짓 수는 O(1)에 조회되므로 시간복잡도는 O(n) 이다. | ||
| * - 별도 배열이 n+1 만큼 필요하므로 O(n)의 공간복잡도를 가진다. | ||
| * 2. 최적화 | ||
| * - 각 단계의 숫자는 계속 가지고 있을 필요 없이 별도 변수로 처리하면 공간복잡도를 O(1)로 최적화 할 수 있다. | ||
| */ | ||
| public int climbStairs(int n) { | ||
| if(n == 1) return 1; | ||
| if(n == 2) return 2; | ||
|
|
||
| int[] steps = new int[n+1]; | ||
| steps[1] = 1; | ||
| steps[2] = 2; | ||
|
|
||
| for(int i=3; i<=n; i++) { | ||
| steps[i] = steps[i-1] + steps[i-2]; | ||
| } | ||
| return steps[n]; | ||
| } | ||
|
Comment on lines
+24
to
+35
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. 가독성 좋은 코드인 거 같습니다! |
||
| } | ||
|
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. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: 왼쪽 누적곱과 오른쪽 누적곱을 이용해 한 배열에서 모든 원소를 구합니다. 공간을 상수로 줄이는 구현도 가능 개선 제안: 추가적인 최적화를 원하면 출력 배열 자체를 공간으로 활용하는 방식이 있습니다. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| /** | ||
| * 0. 풀이 개요 | ||
| * - 시간복잡도 : O(n) | ||
| * - 공간복잡도 : O(n) | ||
| */ | ||
| class Solution { | ||
| /** | ||
| * 1. 풀이 과정 | ||
| * 1.1 이해 | ||
| * - 각 배열의 원소가 본인을 제외한 모든 것이 곱해진 상태를 출력하면 됨. | ||
| * 1.2 제약 | ||
| * - n이 2부터 10^5까지 임. 배열을 순회하는 경우 n^2은 어려워 보임(10^8 기준). 따라서 n log n 이하가 필요 | ||
| * 1.3 아이디어 | ||
| * - 사실 문제를 몇번 풀었어서 외워져 버림 | ||
| * - 시각적으로 보이자면 2개의 배열을 활용하는 셈 | ||
| * - | 배열 원소를 변수로 치환 | a | b | c | d | | ||
| * | prefix 의 상태 | 1 | 1 * a = a | a * b = ab | ab * c = abc | | ||
| * | suffix 의 상태 | bcd | cd | d | 1 | | ||
| * | prefix * suffix | bcd | acd | abd | abc | | ||
| * - 시간복잡도는 n 번씩 두번 순회 하므로 2n 번 순회로 O(n)이 됨. | ||
| * - 공간복잡도는 n 크기 만큼의 배열을 추가로 생성하므로 O(n)이 됨. | ||
| */ | ||
| public int[] productExceptSelf(int[] nums) { | ||
| int prefix = 1; | ||
| int suffix = 1; | ||
|
|
||
| int len = nums.length; | ||
| int[] answer = new int[len]; | ||
|
|
||
| answer[0] = 1; | ||
| for(int i = 1; i < len; i++) { | ||
| answer[i] = prefix * nums[i-1]; | ||
| prefix *= nums[i-1]; | ||
| } | ||
|
|
||
| for(int i = len-1; i >= 0; i--) { | ||
| answer[i] = answer[i] * suffix; | ||
| suffix *= nums[i]; | ||
| } | ||
|
Comment on lines
+24
to
+39
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. prefix, suffix의 변수명이 값이 직관적이지는 않아서 값의 의미를 담으면 좋을 거 같습니다! |
||
|
|
||
| return answer; | ||
| } | ||
| } | ||
|
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. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: 문자 정렬으로 애너그램 여부를 판단하는 직관적인 접근입니다. 개선 제안: 추가로 해시맵을 이용해 선형 시간으로 풀이하는 방법도 있습니다. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| /** | ||
| * 0. 풀이 개요 | ||
| * - 시간복잡도 : O(n log n) | ||
| * - 공간복잡도 : O(n) | ||
| */ | ||
| class Solution { | ||
| /** | ||
| * 1. 풀이 과정 | ||
| * 1.1 문제 이해 | ||
| * - 애너그램이 가능한 문자열인지 판단하는 문제임. 두 문자열 s와 t가 주어지고, t가 s의 애너그램이라면 true를 반환 | ||
| * 1.2 제약 사항 | ||
| * - s, 와 t의 문자열의 길이가 5 * 10^4 이므로 문자열 길이 만큼 순회해야 한다면 O(n^2)은 불가능해 보임. O(n log n) 이하가 필요. | ||
| * - 문자는 반드시 영소문자로만 구성되어 있으나, 만약 Follow up 질문 처럼 유니코드를 포함해야 된다면 이를 포괄하는 자료형이 필요. | ||
| * 1.3 풀이 아이디어 | ||
| * - 문자열을 정렬했을 때, 같은 문자열이라면 애너그램이 될 것. | ||
| * - 문자열의 character를 배열로 만들고 정렬하면, bulit-in 메서드에 의해 O(n log n)의 시간복잡도가 가짐, | ||
| * - 문자열의 길이만큼 character 배열이 필요하므로 2n 만큼의 공간이 더 필요하므로 O(n)의 공간복잡도를 가짐. | ||
| */ | ||
| public boolean isAnagram(String s, String t) { | ||
| char[] arrayS = s.toCharArray(); | ||
| char[] arrayT = t.toCharArray(); | ||
|
|
||
| Arrays.sort(arrayS); | ||
| Arrays.sort(arrayT); | ||
|
|
||
| return Arrays.equals(arrayS, arrayT); | ||
| } | ||
|
Comment on lines
+19
to
+27
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. n log(n) 의 복잡도를 빈도 카운트를 이용해 개선해볼 수도 있을 거 같습니다!
Contributor
Author
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. 빈도 카운트를 이용해서 개선한다는 의미신거죠? 말씀주신대로 문자열의 Character 단위로 빈도 카운트 하는 방법도 있겠네요. |
||
| } | ||
|
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. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: 전위순회 방식으로 각 노드의 범위를 자식 노드에 전달하여 BST 조건을 확인합니다. 개선 제안: 스택 기반 순회로 재귀 깊이를 제거해 공간을 최적화할 수 있습니다. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| /** | ||
| * 0. 풀이 개요 | ||
| * - 시간복잡도 : O(n) | ||
| * - 공간복잡도 : O(n) | ||
| */ | ||
| class Solution { | ||
| /** | ||
| * 1.3 풀이 아이디어 | ||
| * - root의 좌측은 전부 root.value 보다 작아야 하고, 우측은 더 커야함. | ||
| * - 각 부모 노드에 대해 좌측 자식 노드는 값이 더 작아야 하고, 우측은 더 커야함. | ||
| * - 이 검증을 매 노드에 반복하여 이진트리 여부를 체크할 수 있음 | ||
| * - 모든 노드의 갯 수를 n 이라고 할 때 n 개의 노드를 모두 1번 방문하므로 O(n)의 시간복잡도를 가짐 | ||
| * - 별도의 자료구조를 생성하지는 않지만, 콜 스택이 쌓인 상태를 감안 했을 때 최악의 경우 O(n)의 공간복잡도를 가짐. | ||
| */ | ||
| public boolean isValidBST(TreeNode root) { | ||
| return check(root, Long.MIN_VALUE, Long.MAX_VALUE); | ||
| } | ||
|
|
||
| boolean check(TreeNode cursor, long min, long max) { | ||
| if(cursor == null) return true; // 노드가 없는 경우 생략 | ||
| if(cursor.val <= min || cursor.val >= max) return false; | ||
| return check(cursor.left, min, cursor.val) && check(cursor.right,cursor.val, max); | ||
| } | ||
| } |
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.
🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: 정렬 후 원소 고정-투포인터 패턴으로 중복 제거를 잘 처리하고 있습니다. 모든 가능한 삼중합을 한 번씩 탐색합니다.
개선 제안: 현재 구현이 적절해 보입니다.