-
-
Notifications
You must be signed in to change notification settings - Fork 361
[namuuCY] WEEK 02 Solutions #2692
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
ec7bac7
5fa58c3
53b9760
6c52d98
b086edc
1c2fc5b
a4c5df7
36f8ade
d91fc7e
6f9c2e2
455e278
c3308a1
afbe1e0
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,67 @@ | ||
| // 문제 풀이 흐름 | ||
| // 세 개의 변수. 만약 brute-force(3중 for문 -> 3000 ^ 3 이어서 시간복잡도 너무 높음.) -> 어떤 한 값을 고정해서 변수를 줄이자. | ||
| // 그러면 나머지 두 개는? 투 포인터 같은거 쓰면 안되나? | ||
| // 근데 중복되는 경우에 대해서 어떻게 고려함? | ||
| // 중복되는 경우가 너무 많다.. | ||
| // 우선 정렬 먼저 -> 이후 하나 고정하고 나머지 투포인터 생각 | ||
| // 중복되는거 생각나는대로, 음... | ||
|
|
||
| // N = nums.length라 할때 | ||
| // 시간 복잡도 정렬 + for문 1개 * 길이 N 투포인터 | ||
| // = O(N^2) | ||
| // 공간 복잡도 두 가지로 설명 | ||
| // - Arrays.sort() 로 정렬 시 필요한 추가 공간(or 스택)을 따질 경우 : O(log N) | ||
| // - 따지지 않을 경우 : O(1) | ||
|
|
||
| class Solution { | ||
|
|
||
| int[] nums; | ||
| List<List<Integer>> answer = new ArrayList<>(); | ||
|
|
||
| public List<List<Integer>> threeSum(int[] nums) { | ||
| this.nums = nums; | ||
| // 원본 배열 정렬 | ||
| Arrays.sort(nums); | ||
|
|
||
| for (int fixed = 0; fixed < nums.length - 2; fixed++) { | ||
| // fixed가 이전의 값과 동일할 경우 skip | ||
| if (fixed > 0 && nums[fixed] == nums[fixed - 1]) continue; | ||
|
|
||
| // fixed가 양수이면 뒤에도 무조건 양수이므로 break | ||
| if (nums[fixed] > 0) break; | ||
|
|
||
| searchByTwoPointer(fixed); | ||
| } | ||
|
|
||
| return answer; | ||
| } | ||
|
|
||
| private void searchByTwoPointer(int fixedIdx) { | ||
| int leftIdx = fixedIdx + 1; | ||
| int rightIdx = nums.length - 1; | ||
|
|
||
| while (leftIdx < rightIdx) { | ||
| int sum = nums[fixedIdx] + nums[leftIdx] + nums[rightIdx]; | ||
|
|
||
| if (sum == 0) { | ||
| answer.add(Arrays.asList( | ||
| nums[fixedIdx], | ||
| nums[leftIdx], | ||
| nums[rightIdx] | ||
| )); | ||
|
|
||
| // 중복된것에 대해서 조정해줘야함. | ||
|
|
||
| leftIdx ++; | ||
| rightIdx --; | ||
|
|
||
| while (leftIdx < rightIdx && nums[leftIdx] == nums[leftIdx - 1]) leftIdx++; | ||
| while (leftIdx < rightIdx && nums[rightIdx] == nums[rightIdx + 1]) rightIdx--; | ||
| } else if (sum < 0) { | ||
| leftIdx ++; | ||
| } else { | ||
| rightIdx --; | ||
| } | ||
| } | ||
| } | ||
| } |
|
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. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
풀이 1:
|
| 복잡도 | |
|---|---|
| Time | O(n) |
| Space | O(1) |
피드백: 초기 경우에 대한 처리와 반복 갱신 로직이 명확합니다.
개선 제안: 현재 구현이 적절해 보입니다.
풀이 2: Solution.climbStairs (alternative) — Time: O(n) / Space: O(1)
| 복잡도 | |
|---|---|
| Time | O(n) |
| Space | O(1) |
피드백: 주석에 비해 실제 호출부의 구현이 중심이므로 동일 풀이로 간주.
개선 제안: 현재 구현이 적절해 보입니다.
💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| // 문제 풀이 흐름 | ||
| // 누가봐도 점화식 -> DP 문제이다. | ||
| // 자세히 보니 피보나치수열 같음 | ||
| // 1,2번쨰 항일때만 주의해서 풀자. | ||
|
|
||
| // n에 대해서 | ||
| // 시간복잡도 : O(n) | ||
| // 공간복잡도 : O(1) | ||
|
|
||
| class Solution { | ||
| public int climbStairs(int n) { | ||
| if (n == 1) return 1; | ||
| if (n == 2) return 2; | ||
|
|
||
| // 3 = 2 * [1] + [2] | ||
| // 4 = 2 * [2] + [3] | ||
| int doublePrev = 0; | ||
| int prev = 1; | ||
| int current = 2; | ||
|
|
||
| for (int i = 3 ; i <= n ; i++ ) { | ||
| doublePrev = prev; | ||
| prev = current; | ||
| current = doublePrev + prev; | ||
| } | ||
| return current; | ||
| } | ||
| } |
|
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. 이거 저도 잘 몰랐었는데요, 제대로 풀면 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. 말씀하신 것처럼, 제가 요구사항을 지키지 않은 풀이라 틀린풀이라고 보는게 맞는거 같습니다! 또 리트코드 다른 분 풀이를 보니 static 영역을 추가하고
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. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
풀이 1:
|
| 복잡도 | |
|---|---|
| Time | O(n) |
| Space | O(1) |
피드백: 공간을 상수로 유지하면서 두 방향 순회를 이용한 효율적 풀이.
개선 제안: 현재 구현이 적절해 보입니다.
풀이 2: Solution.prevSubmission — Time: O(n) / Space: O(1)
| 복잡도 | |
|---|---|
| Time | O(n) |
| Space | O(1) |
피드백: 제로와 오버플로우 케이스를 다루는 보조 구현이 포함됩니다.
개선 제안: 현재 구현이 적절해 보입니다.
💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| // 문제 풀이 흐름 : | ||
| // 전체의 합에서 자기 자신만 뺀것을 생각하듯이, 전체의 곱에서 자기 자신만 나눈 것을 생각하자 | ||
| // 이때, 중요한 것은 integer overflow와 0이 여러번 나올 떄 예외처리 | ||
| // integer overflow : 문제에서는 답이 32 bit integer 라고 했지, 그 과정에서 생길 수 있는 곱들이 int범위라고 단정지을 수 없음 | ||
| // 0의 개수에 따라 다르게 계산 : | ||
| // 0이 없을 때 : 상관없음. | ||
| // 1개만 있을 때 : 0인 곳에만 product 기입 | ||
| // 2개만 있을 때 : 모두 0이 된다. | ||
|
|
||
| // n = nums.length 라 할때 | ||
| // 시간복잡도 : O(n) | ||
| // 공간복잡도 : O(n) | ||
|
|
||
|
|
||
| class Solution { | ||
|
|
||
| static { | ||
| Solution warmup = new Solution(); | ||
| for (int i = 0; i < 500; ++i) { | ||
| warmup.productExceptSelf(new int[2]); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| public int[] productExceptSelf(int[] nums) { | ||
| int[] answer = new int[nums.length]; | ||
|
|
||
| Arrays.fill(answer, 1); | ||
|
|
||
| int leftProduct = 1; | ||
| for (int i = 0 ; i < nums.length - 1; i ++) { | ||
| leftProduct *= nums[i]; | ||
| answer[i + 1] *= leftProduct; | ||
| } | ||
|
|
||
| int rightProduct = 1; | ||
| for (int i = nums.length - 1 ; i > 0 ; i --) { | ||
| rightProduct *= nums[i]; | ||
| answer[i - 1] *= rightProduct; | ||
| } | ||
|
|
||
| return answer; | ||
| } | ||
|
|
||
| public int[] prevSubmission(int[] nums) { | ||
| int zeros = 0; | ||
| long totalProduct = 1; | ||
|
|
||
| for (int number : nums) { | ||
| if (number == 0) { | ||
| zeros ++; | ||
| } | ||
| totalProduct *= number; | ||
| } | ||
|
|
||
| int[] answer = new int[nums.length]; | ||
|
|
||
| if (zeros == 0) { | ||
| for (int i = 0 ; i < nums.length; i ++ ) { | ||
| answer[i] = (int) (totalProduct / nums[i]); | ||
| } | ||
| } else if (zeros == 1) { | ||
| int nonZeroProduct = 1; | ||
| int zeroIdx = -1; | ||
| for (int i = 0 ; i < nums.length; i ++ ) { | ||
| if (nums[i] == 0) { | ||
| zeroIdx = i; | ||
| continue; | ||
| } | ||
| nonZeroProduct *= nums[i]; | ||
| } | ||
| answer[zeroIdx] = nonZeroProduct; | ||
| } | ||
|
|
||
| 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,29 @@ | ||
| // 문제 풀이 흐름 | ||
| // 아나그램 : 글자 빈도가 같으면 항상 아나그램 관계 | ||
| // 가장 먼저 : 전체 글자수가 같은지 비교 | ||
| // 그 다음 -> 알파벳 별로 빈도수가 같은지 비교 | ||
|
|
||
| // n = max(s의 길이, t의 길이)라고 했을때 | ||
| // 시간복잡도 : O(n) | ||
| // 공간복잡도 : O(1) | ||
|
|
||
| class Solution { | ||
| public boolean isAnagram(String s, String t) { | ||
| int[] sCount = new int[26]; | ||
| int[] tCount = new int[26]; | ||
|
|
||
| if (s.length() != t.length()) return false; | ||
|
|
||
| for (int i = 0 ; i < s.length() ; i++) { | ||
| sCount[s.charAt(i) - 'a'] ++; | ||
| tCount[t.charAt(i) - 'a'] ++; | ||
| } | ||
|
|
||
| for (int i = 0 ; i < 26 ; i++) { | ||
| if (sCount[i] == tCount[i]) continue; | ||
| return false; | ||
| } | ||
|
|
||
| return true; | ||
| } | ||
| } |
|
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. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
풀이 1:
|
| 복잡도 | |
|---|---|
| Time | O(n) |
| Space | O(n) |
피드백: 재귀를 이용한 순회와 전역 변수로 음이 아닌 조건을 충족하며 올바르게 동작합니다.
개선 제안: 현재 구현이 적절해 보입니다.
풀이 2: Solution.visitNode — Time: O(n) / Space: O(n)
| 복잡도 | |
|---|---|
| Time | O(n) |
| Space | O(n) |
피드백: 노드 방문 순서를 정확하게 유지합니다.
개선 제안: 현재 구현이 적절해 보입니다.
💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| // 문제 풀이 흐름 | ||
| // 기억하기로는 트리 순회 하는 방식이 몇 가지 있던거로 기억하는데 | ||
| // 왼쪽 자식 -> 부모 -> 오른쪽 자식 이 방식으로 순회하는 방식을 사용해야함. | ||
| // 그렇게 순회하도록 한 뒤, 순서대로 확인하는데 숫자가 증가하지 않는다면 invalid | ||
| // 순회 아이디어 : 재귀를 이용 + 이전 노드 방문 값을 항상 저장 | ||
| // 맨 처음 노드 방문 값은 -2^32 로 하자 -> 맨 왼쪽 노드는 항상 그 다음이 되도록 | ||
| // param : 현재 노드 | ||
| // 왼쪽 자식이 있다면? 왼쪽 노드 방문, | ||
| // 없으면 무시 | ||
| // 현재 노드 값 valid한지 | ||
| // 오른쪽 자식이 있다면? 오른쪽 노드 방문 | ||
|
|
||
| // n = node 갯수라고 한다면 | ||
| // 시간복잡도 : O(n) | ||
| // 공간복잡도 : 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 { | ||
|
|
||
| long currentValue = -(1L << 33); | ||
|
|
||
| public boolean isValidBST(TreeNode root) { | ||
| return visitNode(root); | ||
| } | ||
|
|
||
|
|
||
| private boolean visitNode(TreeNode node) { | ||
| // 왼쪽 자식 | ||
| if (node.left != null) { | ||
| boolean isValid = visitNode(node.left); | ||
| if (!isValid) return false; | ||
| } | ||
|
|
||
| // 현재 노드 | ||
| if (currentValue >= node.val) return false; | ||
| currentValue = node.val; | ||
|
|
||
| // 오른쪽 자식 | ||
| if (node.right != null) { | ||
| boolean isValid = visitNode(node.right); | ||
| if (!isValid) 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.
🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
풀이 1:
Solution.threeSum— Time: O(n^2) / Space: O(1)피드백: 정렬 후 중복 제거 로직을 통해 중복 결과를 피하는 구성이 잘 되어 있습니다.
개선 제안: 현재 구현이 적절해 보입니다.
풀이 2:
Solution.searchByTwoPointer— Time: O(n^2) / Space: O(1)피드백: 중복 제거를 while 루프로 확실히 처리하고 있어 정확합니다.
개선 제안: 없음