-
-
Notifications
You must be signed in to change notification settings - Fork 363
[seongmin36] WEEK 03 Solutions #2715
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
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,43 @@ | ||
| /** | ||
| 백트래킹(backtracking)을 이용한 풀이 | ||
|
|
||
| candidates 배열이 순차 정렬을 위해 오름차순으로 정렬한다. | ||
| 함수 파라미터는 backtracking(남은 수, 현재 push된 배열, 탐색한 인덱스)를 받는다. | ||
|
|
||
| 동작 원리 | ||
| 1. candidates의 작은 원소부터 하나씩 push하고, 해당 원소를 target에서 차감한다 → remains | ||
| 2. dfs 방식으로 재귀적으로 호출하여 remains가 0이 되면 최종 result 배열에 push된다. | ||
| 3. 여기서 breakpoint는 탐색 인덱스의 값이 remains보다 큰 경우이다. | ||
| 4. 가장 핵심인 부분은 원본 배열에 find_number/remains를 조합할 수 없으면 pop()을 호춣하는데, | ||
| 이는 진행중인 단계에서 더 이상의 조합을 찾지 못해서 다음 조합을 찾기 위한 필수 과정이다. | ||
| */ | ||
| /** | ||
| * @param {number[]} candidates | ||
| * @param {number} target | ||
| * @return {number[][]} | ||
| */ | ||
| function combinationSum(candidates, target) { | ||
| let result = []; | ||
|
|
||
| candidates.sort((a, b) => a - b); | ||
|
|
||
| function backtracking(remains, current, index) { | ||
| if (remains === 0) { | ||
| result.push([...current]); | ||
| } | ||
|
|
||
| for (let i = index; i < candidates.length; i++) { | ||
| let find_number = remains - candidates[i]; | ||
|
|
||
| if (candidates[i] > remains) break; | ||
|
|
||
| current.push(candidates[i]); | ||
| backtracking(find_number, current, i); | ||
| current.pop(); | ||
| } | ||
| } | ||
|
|
||
| backtracking(target, [], 0); | ||
|
|
||
| return result; | ||
| } |
|
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. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: 두 자리 숫자 가능 여부를 isAlphabet로 판단하고 dp 배열에 누적해 경우의 수를 합산한다. 개선 제안: 현재 구현이 적절해 보입니다.
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| /** | ||
| 검증해야되는 케이스는 총 2가지다. | ||
| 1. 1~9까지의 알파벳 | ||
| 2. 10~26까지의 알파벳 | ||
|
|
||
| 우선 맨 앞자리가 '0'인 경우는 항상 0을 반환하도록 한다. | ||
| substring() 메서드를 활용하여 s로부터 특정 범위의 string을 가져와야 한다. | ||
| 1자리일 때(one_char), 2자리일 때(two_char) 케이스를 비교한다. | ||
|
|
||
| 중요한 점은 '비교한 값은 어떻게 저장해야하는가?'이다. | ||
| 여러 방법이 있지만, 'climbing stairs'(피보나치 수열)에서 사용했던 '바텀업 방식의 DP'를 사용한다. | ||
| 바텀업 DP를 사용하는 이유는 두 가지의 케이스의 합을 기억하고 더한 값을 가져와야하기 때문이다. | ||
| */ | ||
|
|
||
| /** | ||
| * @param {string} s | ||
| * @return {number} | ||
| */ | ||
| function numDecodings(s) { | ||
| if (s[0] === "0") return 0; | ||
|
|
||
| let dp = new Array(s.length + 1).fill(0); | ||
|
|
||
| dp[0] = 1; | ||
|
|
||
| function isAlphabet(str) { | ||
| if (str.length === 1) return str >= "1" && str <= "9"; | ||
| if (str.length === 2) return str >= "10" && str <= "26"; | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| for (let i = 1; i < dp.length; i++) { | ||
| let one_char = s.substring(i - 1, i); | ||
| let two_char = s.substring(i - 2, i); | ||
|
|
||
| if (isAlphabet(one_char)) { | ||
| dp[i] += dp[i - 1]; | ||
| } | ||
| if (i >= 2) { | ||
| if (isAlphabet(two_char)) { | ||
| dp[i] += dp[i - 2]; | ||
| } | ||
| } | ||
| } | ||
| return dp[s.length]; | ||
| } |
|
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. 🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: cur_sum과 result를 유지하며 음수 구간을 끊고 최대값을 갱신한다. 개선 제안: 현재 구현이 적절해 보입니다.
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| /** | ||
| 이 문제의 핵심은 연결된 배열이어야 하고, 누적된 값의 합이 음수라면 과감하게 다시 시작하는 것이다. | ||
| 이를 카데인 알고리즘(Kadane's Algorithm)이라고 한다. | ||
| */ | ||
|
|
||
| /** | ||
| * @param {number[]} nums | ||
| * @return {number} | ||
| */ | ||
| function maxSubArray(nums) { | ||
| let result = nums[0]; | ||
| let cur_sum = nums[0]; | ||
|
|
||
| if (nums.length === 1) return nums[0]; | ||
|
|
||
| for (let i = 1; i < nums.length; i++) { | ||
| if (cur_sum <= 0) { | ||
| cur_sum = nums[i]; | ||
| } else if (cur_sum > 0) { | ||
| cur_sum = cur_sum + nums[i]; | ||
| } | ||
|
|
||
| result = Math.max(result, cur_sum); | ||
| } | ||
| return result; | ||
| } |
|
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 & 1으로 하위 비트를 확인하고 무조건 우측으로 시프트하는 루프 방식. 개선 제안: 현재 구현이 적절해 보입니다.
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| /** | ||
| toString(2)으로 해결했다가 다른 분의 풀이를 보고 다시 풀어보았다. | ||
|
|
||
| '비트 연산을 통한 계산'이다. | ||
| 컴퓨터에서 모든 언어는 2진법으로 변환이 되는데, 이를 이용한 플이다. | ||
| 가장 오른쪽 비트가 1인 경우에 count++, n을 우측으로 1칸 shift. | ||
| shift를 하면 결국 남는 숫자는 0이기 때문에 적절한 조건으로 루프를 빠져나온다. | ||
|
|
||
| 굳이 2진법으로 변환하지 않고도 계산할 수 있어서 이게 더 좋은 풀이라 생각하였다. | ||
| */ | ||
| /** | ||
| * @param {number} n | ||
| * @return {number} | ||
| */ | ||
| function hammingWeight(n) { | ||
| let count = 0; | ||
|
|
||
| while (n !== 0) { | ||
| count += n & 1; | ||
| n >>>= 1; | ||
| } | ||
|
|
||
| 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,27 @@ | ||
| /** | ||
| s를 정규식으로 알파벳 소문자 string만 남겨둬야한다. | ||
| 알파벳 소문자만 남겨놓도록 하는 정규식은 '/[^a-z0-9]/gi'이다. | ||
| left(0)와 right(마지막 인덱스)를 동시에 하나씩 줄여가면서 비교 | ||
| */ | ||
|
|
||
| /** | ||
| * @param {string} s | ||
| * @return {boolean} | ||
| */ | ||
| function isPalindrome(s) { | ||
| s = s.replace(/[^a-z0-9]/gi, "").toLowerCase(); | ||
|
|
||
| let left = 0; | ||
| let right = s.length - 1; | ||
|
|
||
| while (left < right) { | ||
| if (s[left] !== s[right]) { | ||
| return false; | ||
| } | ||
|
|
||
| left++; | ||
| right--; | ||
| } | ||
|
|
||
| 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.
🏷️ 알고리즘 패턴 분석
📊 시간/공간 복잡도 분석
피드백: 오름차순 정렬 후 같은 원소를 여러 번 재사용하는 백트래킹 방식으로 해를 찾으며 가지치기를 통해 불필요한 경로를 줄인다.
개선 제안: 현재 구현이 적절해 보입니다.