Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions combination-sum/seongmin36.js

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🏷️ 알고리즘 패턴 분석

  • 패턴: Backtracking
  • 설명: 정렬된 후보를 순차적으로 탐색하며 남은 합을 줄여가고, 조건이 맞으면 부분해를 결과에 추가하는 재귀 탐색 방식으로 구성되어 있어 Backtracking 패턴에 해당합니다.

📊 시간/공간 복잡도 분석

복잡도
Time O(k * n)
Space O(n)

피드백: 오름차순 정렬 후 같은 원소를 여러 번 재사용하는 백트래킹 방식으로 해를 찾으며 가지치기를 통해 불필요한 경로를 줄인다.

개선 제안: 현재 구현이 적절해 보입니다.

💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!

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;
}
47 changes: 47 additions & 0 deletions decode-ways/seongmin36.js

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🏷️ 알고리즘 패턴 분석

  • 패턴: Dynamic Programming, Two Pointers, Hash Map / Hash Set
  • 설명: 주어진 코드는 문자열 분할의 경우의 수를 DP로 계산한다. 총 2자리 또는 1자리 해석 가능 여부를 점진적으로 누적해 비용을 합산하는 바텀업 DP 패턴이 핵심이다. Two Pointers나 Hash Map보다는 DP의 중요 패턴이 가장 두드러진다.

📊 시간/공간 복잡도 분석

복잡도
Time O(n)
Space O(n)

피드백: 두 자리 숫자 가능 여부를 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];
}
26 changes: 26 additions & 0 deletions maximum-subarray/seongmin36.js

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🏷️ 알고리즘 패턴 분석

  • 패턴: Greedy, Dynamic Programming
  • 설명: 코드는 Kadane의 알고리즘으로 연속 부분 배열의 합의 최댓값을 구한다. 현재 합이 음수면 새로운 시작점을 선택하고, 양수면 계속 확장하는 방식으로 최적해를 얻는다. 따라서 Greedy와 DP의 아이디어를 모두 포함하는 대표적 패턴이다.

📊 시간/공간 복잡도 분석

복잡도
Time O(n)
Space O(1)

피드백: 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;
}
24 changes: 24 additions & 0 deletions number-of-1-bits/seongmin36.js

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🏷️ 알고리즘 패턴 분석

  • 패턴: Bit Manipulation, Greedy
  • 설명: 비트 연산으로 1비트를 검사하고 우측으로 시프트하며 순차적으로 카운트하는 방식으로 최적화된 비트 조작 풀이이다. 덧붙여 숫자를 이진수로 변환하지 않고도 1의 개수를 구한다.

📊 시간/공간 복잡도 분석

복잡도
Time O(number of bits)
Space O(1)

피드백: 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;
}
27 changes: 27 additions & 0 deletions valid-palindrome/seongmin36.js

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🏷️ 알고리즘 패턴 분석

  • 패턴: Two Pointers, Greedy
  • 설명: 문자열을 정규화한 뒤 양 끝에서 포인터를 이동시키며 비교하는 방식으로 회문 여부를 판단한다. 두 포인터를 동시에 움직이며 중앙으로 수렴하는 패턴이다.

📊 시간/공간 복잡도 분석

복잡도
Time O(n)
Space O(n)

피드백: 입력 문자열을 정규화하고 양 끝에서 투포인터로 비교한다.

개선 제안: 현재 구현이 적절해 보입니다.

💡 풀이에 시간/공간 복잡도를 주석으로 남겨보세요!

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;
}
Loading