-
-
Notifications
You must be signed in to change notification settings - Fork 363
[dahyeong-yun] WEEK 03 Solutions #2724
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
52b6d7f
c831f91
b453ac3
9c0457e
2cb2b3d
4e0c9d3
e77b436
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,60 @@ | ||
| /** | ||
| * [풀이 개요] | ||
| * - 시간복잡도 : O(H(N, M) * M) | ||
| * - 공간복잡도 : O(H(N, M) * M) (정답 배열 제외 시 O(M)) | ||
| */ | ||
| class Solution { | ||
| /** | ||
| * [문제 풀이 아이디어] | ||
| * - candidates 배열의 수를 조합해서 target을 만드는 조합을 중복되는 조합 없이 찾아야 함. | ||
| * - 각 원소는 중복이 될 수 있음. 이 때문에 candidates을 여러번 반복해서 찾아야 함. 조합이 되는 배열의 길이가 동적이므로 재귀적으로 확인해야 할 듯. | ||
| * - 시공간복잡도의 경우, 중복 조합의 개수를 계산해야 하는 건 알겠는데, 계산이 직관적으로는 이해가 잘 안됨. O(H(N, M) * M) | ||
| */ | ||
| private List<List<Integer>> answer = new ArrayList<>(); | ||
|
|
||
| public List<List<Integer>> combinationSum(int[] candidates, int target) { | ||
| backtracking(0, 0, target, candidates, new ArrayList<>()); | ||
| return answer; | ||
| } | ||
|
|
||
| /** | ||
| * [시뮬레이션: 인덱스 & Sum 추적] | ||
| * 형식: [인덱스 조합] (계산 과정) = 현재Sum | ||
| * * * 시작 (Sum = 0) | ||
| * ├── [0] (+2) = Sum: 2 | ||
| * │ ├── [0, 0] (+2) = Sum: 4 | ||
| * │ │ ├── [0, 0, 0] (+2) = Sum: 6 | ||
| * │ │ │ └── [0, 0, 0, 0] (+2) = Sum: 8 ❌ (Over 7) | ||
| * │ │ └── [0, 0, 1] (+3) = Sum: 7 ★ 정답 [2, 2, 3] | ||
| * │ ├── [0, 1] (+3) = Sum: 5 | ||
| * │ │ └── [0, 1, 1] (+3) = Sum: 8 ❌ (앞의 2로 못 돌아감) | ||
| * │ └── [0, 2] (+6) = Sum: 8 ❌ | ||
| * │ | ||
| * ├── [1] (+3) = Sum: 3 <-- 이제 이전 인덱스인 0번(값 2)은 영구 제외 | ||
| * │ ├── [1, 1] (+3) = Sum: 6 | ||
| * │ │ └── [1, 1, 1] (+3) = Sum: 9 ❌ | ||
| * │ └── [1, 2] (+6) = Sum: 9 ❌ | ||
| * │ | ||
| * ├── [2] (+6) = Sum: 6 | ||
| * │ └── [2, 2] (+6) = Sum: 12 ❌ | ||
| * │ | ||
| * └── [3] (+7) = Sum: 7 ★ 정답 [7] | ||
| */ | ||
| public void backtracking(int start, int sum, int target, int[] candidates, List<Integer> list) { | ||
| if(sum == target) { | ||
| answer.add(new ArrayList<>(list)); | ||
| return; // 🎯 정답을 찾았으므로 즉시 탈출 (효율성 증가) | ||
| } | ||
|
|
||
| if(sum > target) { | ||
| return; | ||
| } | ||
|
|
||
| // 🎯 i = start 및 재귀 인자 i로 변경하여 주석의 '중복 조합' 로직 완성 | ||
| for(int i = start; i < candidates.length; i++) { | ||
| list.add(candidates[i]); | ||
| backtracking(i, sum + candidates[i], target, candidates, list); | ||
| list.remove(list.size() - 1); | ||
| } | ||
| } | ||
| } |
|
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. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: 상태를 start 인덱스로 두고 한 자리 또는 두 자리로 파싱 가능한 경우를 재귀적으로 합산한다. DP 배열로 중복 계산을 방지한다. 개선 제안: 현재 구현이 적절해 보입니다. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| /** | ||
| * [풀이 개요] | ||
| * - 시간복잡도 : O(n) | ||
| * - 공간복잡도 : O(n) | ||
| */ | ||
| class Solution { | ||
| /** | ||
| * [문제 풀이 아이디어] | ||
| * - 한 글자로 파싱이 되는 경우의 수와 두 글자로 파싱이 되는 경우 수를 합하면 될 것 같음 | ||
| * - 시간복잡도는 각 인덱스를 처음 한번 들린 이 후로는 dp 배열에서 O(1)에 리턴하므로 O(n). | ||
| * - 공간복잡도는 문자열 길이 만큼의 dp 배열을 생성하므로 O(n) | ||
| */ | ||
| public int numDecodings(String s) { | ||
| int len = s.length(); | ||
| int[] dp = new int[len + 1]; | ||
| Arrays.fill(dp, -1); | ||
| return count(0, s, len, dp); | ||
| } | ||
|
|
||
| /** | ||
| * [시뮬레이션] | ||
| * Case : 226 | ||
| * count(0, 226, {-1,-1,-1}) | ||
| * += count(1, 226, {-1,-1,-1}) return 2 / 2 | ||
| * += count(2, 226, {-1,-1,-1}) return 1 / 2 2 | ||
| * += count(3, 226, {-1,-1,-1}) return 1 / 2 2 6 | ||
| * += 0 (4 > limit) | ||
| * += count(3, 226, {-1,-1,-1}) return 1 / 2 26 / cashing | ||
| * += count(2, 226, {-1,-1,-1}) return 1 / 22 / cashing | ||
| * += count(3, 226, {-1,-1,-1}) return 1 / 22 6 / cashing | ||
| * = 1 + 2 = 3 | ||
| */ | ||
| public int count(int start, String s, int limitIndex, int[] dp) { | ||
| if(start == limitIndex) { | ||
| return 1; | ||
| } | ||
| // 0으로 시작할 수 없음 | ||
| if(s.charAt(start) == '0') { | ||
| return 0; | ||
| } | ||
|
|
||
| if(dp[start] != -1) { | ||
| return dp[start]; | ||
| } | ||
|
|
||
| int totalWays = 0; | ||
|
|
||
| if(start + 1 <= limitIndex) { | ||
| totalWays += count(start + 1, s, limitIndex, dp); | ||
| } | ||
|
|
||
| if(start + 2 <= limitIndex) { | ||
| String numStr = s.substring(start, start+2); | ||
| if(Integer.parseInt(numStr) <= 26) { | ||
| totalWays += count(start + 2, s, limitIndex, dp); | ||
| } | ||
| } | ||
| dp[start] = totalWays; | ||
| return totalWays; | ||
| } | ||
| } |
|
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,25 @@ | ||
| /** | ||
| * [풀이 개요] | ||
| * - 시간복잡도 : O(n) | ||
| * - 공간복잡도 : O(1) | ||
| */ | ||
| class Solution { | ||
| /** | ||
| * [문제 풀이 아이디어] | ||
| * - 연속된 부분 배열 합의 최대를 구하는 문제. 즉, 카데인 알고리즘을 떠올릴 수 있음 | ||
| * - 수 배열을 한번 순회 하므로 시간복잡도는 O(n) | ||
| * - 별도 공간 할당이 없으므로 공간복잡도는 O(1) | ||
| */ | ||
| public int maxSubArray(int[] nums) { | ||
| int max = nums[0]; | ||
| int current = nums[0]; | ||
|
|
||
| int len = nums.length; | ||
| for(int i=1; i<len; i++) { | ||
| current = Math.max(nums[i], current + nums[i]); | ||
| max = Math.max(current, max); | ||
| } | ||
|
|
||
| return max; | ||
| } | ||
| } |
|
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. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: 128비트까지의 정수에 대해서 비트 카운트 연산을 수행한다. 보조 풀이도 함께 첨부되어 있다. 개선 제안: 현재 구현이 적절해 보입니다. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| /** | ||
| * [풀이 개요] | ||
| * - 시간복잡도 : O(1) | ||
| * - 공간복잡도 : O(1) | ||
| */ | ||
| class Solution { | ||
| public int hammingWeight(int n) { | ||
| return Integer.bitCount(n); | ||
| } | ||
|
|
||
| /** 참고 | ||
| @IntrinsicCandidate | ||
| public static int bitCount(int i) { | ||
| // HD, Figure 5-2 | ||
| i = i - ((i >>> 1) & 0x55555555); | ||
| i = (i & 0x33333333) + ((i >>> 2) & 0x33333333); | ||
| i = (i + (i >>> 4)) & 0x0f0f0f0f; | ||
| i = i + (i >>> 8); | ||
| i = i + (i >>> 16); | ||
| return i & 0x3f; | ||
| } | ||
| */ | ||
|
|
||
| /** | ||
| * [문제 풀이 아이디어] | ||
| * - 10진수를 2진수로 표현했을 때 1의 갯 수를 세야함. | ||
| * - 10진수를 2로 나눈 몫이 0이 될 때까지 나누고, 각각의 나머지를 역으로 적으면 2진수가 됨. | ||
| * - 따라서 각 나눗셈의 나머지가 1인 경우를 카운트 할 수 있음 | ||
| * - 진법 변환 예시 | ||
| * - 10 % 2 = 5, 0 - 2^0 | ||
| * - 5 % 2 = 2, 1 - 2^1 | ||
| * - 2 % 2 = 1, 0 - 2^2 | ||
| * - 1 % 2 = 0, 1 - 2^3 | ||
| * - 10 => 1010 | ||
| * - int는 32비트 자료형으로 최대 32번 반복하므로 시간복잡도는 상수시간으로 봐도 무방, O(1) | ||
| * - 별도 공간이 유의미한 공간할당을 하고 있지 않으므로 공간복잡도는 0(1) | ||
| */ | ||
| public int hammingWeight(int n) { | ||
| int count = 0; | ||
| while(n > 0) { | ||
| count += n % 2; | ||
| n /= 2; | ||
| } | ||
| return count; | ||
| } | ||
| } |
|
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 @@ | ||
| /** | ||
| * [풀이 개요] | ||
| * - 시간복잡도 : O(n) | ||
| * - 공간복잡도 : O(1) | ||
| */ | ||
| class Solution { | ||
| /** | ||
| * [문제 풀이 아이디어] | ||
| * - 주어진 문자열의 길이가 최대 10^5 이므로 10^8 까지 통과할 수 있다고 가정할 때, 시간복잡도는 O (n log n)까지 가능해 보임 | ||
| * - 문자열 s의 시작과 끝 인덱스가 각각 x, y 라고 할 때 s[x] == s[y], s[x+1] == s[y-1], s[x+2] == s[y-2], s[x+n] == s[y-n] (n은 문자열 중간 인덱스 까지) 와 같이 검증할 수 있음. | ||
| * - 즉 투포인터 형태가 될 수 있어 보임. | ||
| * - 다만 알파벳이 아닌 문자는 제외하고 판단해야 하므로 포인터가 정확히 같은 값을 x, y에서 빼는 형태가 될 수는 없고, 비교 대상이 아닌 인덱스를 넘어가서 다음에 판단해야 함. | ||
| * - 이렇게 순회할 경우 문자열 길이 n의 1/2 를 순회하므로 시간복잡도는 O(n) 이 됨. | ||
| * - 매 char 변수 이외에 추가 공간이 필요치 않으므로 공간복잡도는 O(1) 이 됨. | ||
| */ | ||
| public boolean isPalindrome(String s) { | ||
| int len = s.length(); | ||
| if(len == 1) return true; | ||
|
|
||
| int left = 0; | ||
| int right = len - 1; | ||
|
|
||
| while(left < right) { | ||
| char leftChar = Character.toLowerCase(s.charAt(left)); | ||
| char rightChar = Character.toLowerCase(s.charAt(right)); | ||
|
|
||
| // 문자가 아닌 경우 다음 인덱스 확인 | ||
| if(!Character.isLetterOrDigit(leftChar)) { | ||
| left++; | ||
| } else if(!Character.isLetterOrDigit(rightChar)) { | ||
| right--; | ||
|
|
||
| // 동일한 경우 다음 인덱스 확인 | ||
| } else if(leftChar == rightChar) { | ||
| left++; | ||
| right--; | ||
| } else { | ||
| 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.
🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: 백트래킹으로 중복 조합을 고려하되 시작 인덱스를 i로 고정하여 중복 조합을 제거하고 합이 타깃을 넘으면 가지치기를 한다.
개선 제안: 현재 구현이 적절해 보입니다.