Skip to content
57 changes: 57 additions & 0 deletions 3sum/togo26.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, Sorting, Greedy, Binary Search
  • 설명: 주요 로직은 정렬 후 두 포인터(left, right)를 활용해 합이 0인 서로 다른 세 수를 찾는 방식이다. 중복 제거를 위해 두 포인터 이동 시 값 비교를 수행한다. 따라서 Two Pointers 패턴이 핵심이며, 코드에 직접적으로 구현된 정렬과 조건 확인으로 추가적인 최적화가 포함된다.

📊 시간/공간 복잡도 분석

유저 분석 실제 분석 결과
Time O(n^2) O(n^2)
Space O(n^2) O(1)

피드백: 입력 배열을 한 번 정렬하고, 각 i에 대해 좌우 포인터를 이동시키며 결과를 수집합니다. 중복 제거를 위해 i, left, right의 중복 카운트를 신경 씁니다.

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/**
* @param {number[]} nums
* @return {number[][]}
*/
/// TC: TLE / SC: O(n)
// var threeSum = function(nums) {
// const result = [];
// const memo = {};

// for (let i = 0; i < nums.length; i++) {
// for (let j = 0; j < nums.length; j++) {
// for (let k = 0; k < nums.length; k++) {
// if (i === k || i === j || j === k) continue;
// const comb = [nums[i], nums[j], nums[k]].sort((a, b) => a - b).join(",");

// if (memo[comb]) continue;
// if (!memo[comb]) memo[comb] = true;
// const sum = nums[i] + nums[j] + nums[k];
// if (sum === 0) result.push([nums[i], nums[j], nums[k]]);
// }
// }
// }

// return result;
// };

// TC: O(n^2) / SC: O(1)
var threeSum = function (nums) {
const result = [];

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

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

let left = i + 1;
let right = nums.length - 1;

while (left < right) {
const sum = nums[left] + nums[right];
if (sum === -nums[i]) {
result.push([nums[i], nums[left], nums[right]]);
while (left < right && nums[left] === nums[left + 1]) left++;
while (left < right && nums[right] === nums[right - 1]) right--;
left++;
right--;
} else if (sum < -nums[i]) {
left++;
} else {
right--;
}
}
}

return result;
};
Comment on lines +28 to +57

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.

막히는 지점 없이 잘 읽히는 코드인 거 같습니다! 👍

28 changes: 28 additions & 0 deletions climbing-stairs/togo26.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, Monotonic Stack
  • 설명: climbStairs는 피보나치 계열의 합으로 구성되는 DP 문제로 각 단계의 경우의 수를 이전 값들로 계산한다. 반복을 통한 상태 전이가 핵심이며, 최적 부분구조를 이용한 DP 패턴으로 분류된다.

📊 시간/공간 복잡도 분석

유저 분석 실제 분석 결과
Time O(n) O(n)
Space O(n) O(n)

피드백: 첫 구현은 배열을 이용한 DP이고, 두 번째 구현은 상수 공간으로 최적화했습니다.

개선 제안: 메모리 사용을 줄이는 방향은 이미 반영되어 있습니다.

Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* @param {number} n
* @return {number}
*/

// TC: O(n) / SC: O(n)
var climbStairs = function (n) {
if (n <= 3) return n;
const dp = [1, 2, 3];
for (let i = 3; i < n; i++) {
dp[i] = dp[i - 2] + dp[i - 1];
}

return dp[dp.length - 1];
};

// TC: O(n) / SC: O(1)
var climbStairs = function (n) {
let temp,
pre1 = 1,
pre2 = 1;
for (let i = 1; i < n; i++) {
temp = pre2;
pre2 = pre1 + pre2;
pre1 = temp;
}
return pre2;

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.

첫 번째 풀이가 점화식이 한 눈에 보여서 가독성은 더 좋은 거 같네요!

두번 째 풀이도 공간복잡도가 유리해서 좋은데요. pre1, pre2가 단순히 선언 순서에 따라 1, 2 인지 현재 포인터 기준으로 1,2 번째 전인건지 간단한 주석이 있어도 좋을 거 같습니다!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

좋은 의견 감사합니다! 변수명이 애매하긴했는데 다음번에는 주석으로 보조 설명 붙여보겠습니다.

};
37 changes: 37 additions & 0 deletions product-of-array-except-self/togo26.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, Dynamic Programming, Hash Map / Hash Set
  • 설명: 두 풀이 모두 배열의 각 원소에 대해 다른 원소의 곱의 누적값을 미리 계산해 결과를 구한다. 왼쪽 누적곱과 오른쪽 누적곱의 곱으로 각 위치의 결과를 얻는 기법은 DP와 두 포인터의 묶음으로 볼 수 있다. 또한 공간 절약 버전은 한 배열에 누적값을 갱신하는 형태로 구현된다.

📊 시간/공간 복잡도 분석

유저 분석 실제 분석 결과
Time O(n) O(n)
Space O(n) O(n)

피드백: 두 패스으로 좌우 곱을 구하고 최종적으로 곱을 계산합니다. 추가 배열 사용으로 직관적입니다.

개선 제안: 추가 배열 사용을 줄이고 무시 가능한 공간 최적화도 고려 가능.

Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// TC: O(n) / SC: O(n)
var productExceptSelf = function (nums) {
const left = [1];
const right = [1];
const result = [];

for (let i = 1; i < nums.length; i++) {
left.push(left[i - 1] * nums[i - 1]);
}

for (let i = nums.length - 1; i > 0; i--) {
right.push(right[nums.length - 1 - i] * nums[i]);
}

for (let i = 0, j = nums.length - 1; i < nums.length; i++, j--) {
result[i] = left[i] * right[j];
}

return result;
};

// TC: O(n) / SC: O(1)
var productExceptSelf = function (nums) {
const left = new Array(nums.length).fill(1);

for (let i = 1; i < nums.length; i++) {
left[i] = left[i - 1] * nums[i - 1];
}

let rightProduct = 1;
for (let i = nums.length - 1; i >= 0; i--) {
left[i] *= rightProduct;
rightProduct *= nums[i];
}

return left;
};
Comment on lines +2 to +37

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.

첫번째 풀이가 left, right, result를 각각 집중해서 처리하는 로직이라 쉽게 이해가 가는 것 같네요!

25 changes: 25 additions & 0 deletions valid-anagram/togo26.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, Dynamic Programming
  • 설명: 두 문자열의 문자 빈도를 비교하기 위해 해시맵으로 카운트하는 부분이 핵심이며, 각 문자 등장 횟수를 비교하는 방식은 해시 맵 패턴에 속합니다. 또한 입력 길이가 같음을 확인하고 두 해시맵의 값을 비교하는 흐름은 패턴의 대표적인 활용 예로 간주됩니다. 다만 특정 투포인터나 슬라이딩 윈도우보다는 해시 맵 기반의 비교가 주를 이룹니다.

📊 시간/공간 복잡도 분석

유저 분석 실제 분석 결과
Time O(nlogn) O(n log n)
Space O(nlogn) O(n)

피드백: 첫 번째 구현은 정렬으로 단순하고 두 번째 구현은 해시맵으로 선형 시간에 비교합니다.

개선 제안: 대부분의 경우 해시맵 버전이 더 최적화에 유리합니다.

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* @param {string} s
* @param {string} t
* @return {boolean}
*/
// TC: O(nlogn) / SC: O(n)
var isAnagram = function (s, t) {
const sortedS = [...s].sort().join('');
const sortedT = [...t].sort().join('');
return sortedS === sortedT;
};

// TC: O(n) / SC: O(n)
var isAnagram = function (s, t) {
if (s.length !== t.length) return false;
const sCount = [...s].reduce((acc, cur) => {
acc[cur] = (acc[cur] ?? 0) + 1;
return acc;
}, {});
const tCount = [...t].reduce((acc, cur) => {
acc[cur] = (acc[cur] ?? 0) + 1 ;
return acc;
}, {});
return Object.keys(sCount).every(key => sCount[key] === tCount[key]);
};
Comment thread
togo26 marked this conversation as resolved.
14 changes: 14 additions & 0 deletions validate-binary-search-tree/togo26.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, Depth-First Search, Binary Tree
  • 설명: 루트-좌우 자식 노드의 값 범위를 재귀로 추적하며 BST 조건을 만족하는지 검사하므로, 이 코드는 이진 탐색 트리 검사와 깊이 우선 탐색의 조합으로 분류됩니다. 최소/최대 경계 값을 이용한 탐색으로 패턴을 매칭합니다.

📊 시간/공간 복잡도 분석

유저 분석 실제 분석 결과
Time O(n) O(n)
Space O(n) O(h)

피드백: 각 노드를 정확한 범위 안에 있는지 확인하며 재귀적으로 자식들을 검사합니다.

개선 제안: 스택 기반의 구현으로도 공간 복잡도를 제어 가능.

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* @param {TreeNode} root
* @return {boolean}
*/
// TC: O(n) / SC: Best O(height) - Worst O(n)
var isValidBST = function (root) {
function traverse(node, min, max) {
if (!node) return true;
if (!(min < node.val && node.val < max)) return false;
return traverse(node.left, min, node.val) && traverse(node.right, node.val, max);
Comment on lines +8 to +10

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.

가독성 좋게 잘 풀어주신 거 같습니다!

}

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