Skip to content
41 changes: 41 additions & 0 deletions 3sum/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, Hash Map / Hash Set, Greedy, Sorting
  • 설명: 정렬된 배열에서 i를 고정하고 나머지에서 두 수의 합으로 0을 만드는 짝을 찾기 위해 Set을 사용해 역원을 확인한다. 한 번의 외부 루프와 내부 루프 조합으로 부분적으로 투 포인터처럼 동작하지만, 실제로는 해시셋으로 탐색하는 패턴과 중복 제거 로직이 포함되어 있다. 전체적으로 3SUM 문제의 탐색 전략으로 해시 맵/셋과 정렬의 조합을 사용한다.

📊 시간/공간 복잡도 분석

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

피드백: 정렬 후 외부 루프를 두고 내부에서 중복 제거를 위한 처리와 보조 집합(pocket)을 사용한다.

개선 제안: 현재 구현은 시간복잡도가 O(n^2)인 구조를 잘 따르고 있다. 중복 제거를 배열 인덱스 비교로도 가능하지만, Set 사용으로도 안정적이다.

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
중요한 것은 짝을 찾는 것이다.
즉, 정수가 0이 되는 '역원(inverse)'을 찾아야 한다.
역원을 담을 저장소가 필요한데,
찾아야할 역원은 여러개일 필요가 없기 때문에 주머니 역할로 Set 인스턴스를 사용한다.
중복 조건은 정렬된 배열에서 현재 인덱스보다 큰 원소 중에서 동일한 값을 제외한다.
*/
/**
* @param {number[]} nums
* @return {number[][]}
*/

function threeSum(nums) {
let result = [];

nums.sort((a, b) => a - b);

for (let i = 0; i < nums.length; i++) {
if (nums[i] > 0) break;

// 중복 제거 → i>0 이웃한 두 수가 일치하면 skip
if (i > 0 && nums[i] === nums[i - 1]) continue;

let pocket = new Set();

for (let g = i + 1; g < nums.length; g++) {
let find_num = -(nums[i] + nums[g]);

if (pocket.has(find_num)) {
result.push([nums[i], find_num, nums[g]]);

// 중복 제거 → 정렬된 상태에서 같은 수가 나오면 shift
while (g + 1 < nums.length && nums[g] === nums[g + 1]) {
g++;
}
}
pocket.add(nums[g]);
}
}
return result;
}
18 changes: 18 additions & 0 deletions climbing-stairs/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
  • 설명: 2단계 점프와 1단계 점프의 합으로 수를 누적 계산하는 전형적인 DP 문제이며, 이전 상태의 결과를 이용해 현재 값을 구한다.

📊 시간/공간 복잡도 분석

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

피드백: 배열을 활용해 앞선 두 경우의 합으로 현재 경우의 수를 구한다.

개선 제안: 추가 공간 없이 상수 공간으로 구현할 수도 있다.

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* @param {number} n
* @return {number}
*/
function climbStairs(n) {
if (n <= 2) return n;

let arr = new Array(n + 1);

arr[0] = 1;
arr[1] = 2;

for (let i = 2; i < arr.length; i++) {
arr[i] = arr[i - 2] + arr[i - 1];
}

return arr[n - 1];
}
34 changes: 34 additions & 0 deletions product-of-array-except-self/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
  • 설명: 배열의 각 위치에 대해 자신을 제외한 곱을 구하기 위해 좌우 두 지점을 동시에 진행하는 두 포인터 방식이다. left와 right를 각각 관리하며 중간 중복 없이 누적 곱을 업데이트한다.

📊 시간/공간 복잡도 분석

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

피드백: 왼쪽 곱과 오른쪽 곱을 누적해 각 위치의 값을 업데이트한다.

개선 제안: 추가 공간 사용을 최소화하려면 출력 배열을 이용해 더 최적화 가능하다.

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
문제의 핵심은 '어떻게 인덱스와 곱을 이중 반복문을 쓰지 않고 해결하느냐'다. 'Goal' → 시간 복잡도 : O(N)
여기서 사용된 개념: 'Two Pointer'
Two Pointer? → '배열에서 순차적으로 접근해야 할 때 두 개의 점의 위치를 기록하면서 처리하는 알고리즘'
이중 반복을 사용하지 않고, 각 인덱스를 순회하면서 answer[index]에 본인을 제외한 곱셈을 중첩시킨다.
본인을 제외한 나머지 원소의 곱이기 때문에 left와 right로 나눠서 중첩된 곱셈을 다시 곱한다.
*/

/**
* @param {number[]} nums
* @return {number[]}
*/
function productExceptSelf(nums) {
let answer = new Array(nums.length).fill(1);

let left = 0;
let right = nums.length - 1;

let mul_left = 1;
let mul_right = 1;

while (left < nums.length && right >= 0) {
answer[left] *= mul_left;
mul_left *= nums[left]; // 자기 자신 제외 곱

answer[right] *= mul_right;
mul_right *= nums[right];

left++;
right--;
}

return answer;
}
31 changes: 31 additions & 0 deletions valid-anagram/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.

🏷️ 알고리즘 패턴 분석

  • 패턴: Hash Map / Hash Set, Two Pointers
  • 설명: 두 문자열의 문자 빈도를 해시맵으로 카운트하고 비교하며, 한 문자열에서 다른 문자열의 문자를 차감하는 방식은 해시 맵 활용 패턴이다. 빠른 비교를 위해 포인터를 순회하는 형태로 구현되어 두 문자열 길이 일치 여부를 먼저 검사한다.

📊 시간/공간 복잡도 분석

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

피드백: 두 문자열의 길이가 다르면 바로 false를 반환하고, 한 문자열의 문자 카운트를 맵에 기록한 뒤 다른 문자열로 차감한다.

개선 제안: 알파벳 문자 제한이 있다면 고정 크기 배열로도 구현 가능하다.

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
결국 같아야 것은 string의 길이와 안에 들어간 각 character의 갯수다.
즉, s와 t의 문자의 갯수와 같으면 된다.
map을 사용하여 key와 value자리에 각각 문자, 갯수를 받는다.
s와 t를 비교하며 해당하는 문자 갯수-1을 한다.
각 key의 value를 문제없이 차감했다면 true를 반환. 그 외 false를 반환
*/

/**
* @param {string} s
* @param {string} t
* @return {boolean}
*/
function isAnagram(s, t) {
if (s.length !== t.length) return false;

let map_s = new Map();

for (let char of s) {
map_s.set(char, (map_s.get(char) || 0) + 1);
}

for (let char of t) {
if (!map_s.has(char) || map_s.get(char) === 0) {
return false;
}
map_s.set(char, map_s.get(char) - 1);
}

return true;
}
32 changes: 32 additions & 0 deletions validate-binary-search-tree/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.

🏷️ 알고리즘 패턴 분석

  • 패턴: Binary Search, DFS, Monotonic Stack, Two Pointers, Sliding Window, Breadth-First Search, Backtracking, Dynamic Programming, Hash Map / Hash Set, Greedy, Divide and Conquer, Union Find, Trie, Bit Manipulation, Heap / Priority Queue, Hash Map / Hash Set
  • 설명: 재귀 DFS로 트리의 각 노드를 확인하며 부등식 제약을 만족하는지 검사한다. 루트에서 시작해 왼쪽은 더 작고 오른쪽은 더 커야 한다는 BST 특성을 min/max 경계값으로 재귀적으로 검증한다.

📊 시간/공간 복잡도 분석

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

피드백: 재귀적으로 왼쪽은 min, 현재값, 오른쪽은 현재값, max로 탐색하며 조건 검사를 한다.

개선 제안: 깊이가 큰 트리에서 스택 오버플로우를 우려한다면 비재귀 DFS로 바꿀 수 있다.

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
이진 탐색 트리의 특징은 다음과 같다.
- 부모 노드를 기준으로 left는 부모보다 작은 수
- 부모 노드를 기준으로 right는 부모보다 큰 수
이 문제에서 구하려는 것은 '주어진 트리가 이진 탐색 트리를 만족하는가?'이다
이는 재귀함수를 사용하여 깊이 우선 탐색(DFS)을 통해 해결할 수 있다.
여기서 validate는 'BST'의 특징을 비교하는 함수인데,
validate()는 validate를 반환하면서 깊이 탐색하여 최종 참/거짓을 판별한다.
*/
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {boolean}
*/
function isValidBST(root) {
function validate(p, min, max) {
if (p === null) return true;

if (p.val <= min || p.val >= max) return false;

return validate(p.left, min, p.val) && validate(p.right, p.val, max);
}

return validate(root, -Infinity, Infinity);
}
Loading