Skip to content
Merged
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
13 changes: 13 additions & 0 deletions contains-duplicate/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
  • 설명: 이 코드는 중복 여부를 빠르게 검사하기 위해 Set 자료구조를 사용하여 해시 기반의 검색을 활용하는 패턴입니다.

📊 시간/공간 복잡도 분석

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

피드백: Set을 사용하여 배열의 모든 요소를 저장하고 크기 비교로 중복 여부를 판단하므로 시간 복잡도는 배열 길이 n에 비례합니다. 공간 복잡도도 저장된 요소 수에 따라 O(n)입니다.

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

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* @param {number[]} nums
* @return {boolean}
*/
var containsDuplicate = function (nums) {
const numsSet = new Set(nums);
return numsSet.size !== nums.length;
};

/*
TC: O(n) -> nums 개수 만큼
SC: O(n) -> 중복 삭제 후 요소 수 만큼 메모리 사용
*/
43 changes: 43 additions & 0 deletions house-robber/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
  • 설명: 이 코드는 연속된 집을 훔칠 때 최대 금액을 계산하는 문제로, 이전 상태를 기반으로 최적의 선택을 반복하여 해결하는 동적 계획법 패턴을 사용합니다.

📊 시간/공간 복잡도 분석

ℹ️ 이 파일에는 2가지 풀이가 포함되어 있어 각각 분석합니다.

풀이 1: rob — Time: O(n) / Space: O(n)
복잡도
Time O(n)
Space O(n)

피드백: 배열 크기만큼 반복하며 각 위치별 최적값을 계산하므로 시간 복잡도는 O(n). DP 배열을 저장하는데 배열 크기만큼 공간이 필요하여 공간 복잡도도 O(n).

개선 제안: 두 번째 구현은 공간을 최적화하여 O(1)로 줄였으니 참고하세요.

풀이 2: rob — Time: O(n) / Space: O(1)
복잡도
Time O(n)
Space O(1)

피드백: 배열을 사용하지 않고 두 변수만으로 상태를 갱신하므로 시간 복잡도는 O(n), 공간 복잡도는 O(1)입니다.

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

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

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

for (let i = 0; i < nums.length; i++) {
if (i === 0) {
pocket[i] = nums[i];
continue;
}
if (i === 1) {
pocket[i] = Math.max(nums[i - 1], nums[i]);
continue;
}

pocket[i] = Math.max(pocket[i - 2] + nums[i], pocket[i - 1]);
}

return Object.values(pocket).reduce((acc, cur) => Math.max(acc, cur), 0);
};

/*
TC: O(n)
SC: O(1) -> variable used
*/
var rob = function (nums) {
let prev2 = 0;
let prev1 = 0;

for (let i = 0; i < nums.length; i++) {
let temp = prev1;
prev1 = Math.max(prev2 + nums[i], prev1);
prev2 = temp;
}

return prev1;
};
63 changes: 63 additions & 0 deletions longest-consecutive-sequence/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, Sliding Window
  • 설명: 이 코드는 Set을 이용해 중복 제거와 빠른 탐색을 하며, 연속된 수열을 찾기 위해 시작점을 기준으로 확장하는 슬라이딩 윈도우와 유사한 방식을 사용합니다.

📊 시간/공간 복잡도 분석

ℹ️ 이 파일에는 2가지 풀이가 포함되어 있어 각각 분석합니다.

풀이 1: longestConsecutive — Time: O(n) / Space: O(n)
복잡도
Time O(n)
Space O(n)

피드백: Set을 통해 존재 여부를 빠르게 확인하며, 각 수의 시작점에서만 연속 수를 세기 때문에 전체 시간은 O(n). 공간은 Set 저장에 따라 O(n).

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

풀이 2: longestConsecutive (주석처리 버전) — Time: 복잡도 분석 어려움 (메모리 초과로 인해 실제 실행 불가) / Space: O(maxValue - minValue)
복잡도
Time 복잡도 분석 어려움 (메모리 초과로 인해 실제 실행 불가)
Space O(maxValue - minValue)

피드백: 이 방법은 값의 범위가 크면 메모리 초과가 발생할 수 있어 비효율적입니다. Set을 이용하는 방법이 더 적절합니다.

개선 제안: 이 구현은 개선이 필요하며, 현재 사용된 방법은 추천하지 않습니다.

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* @param {number[]} nums
* @return {number}
*/

/*
TC: O(n) -> for의 skip 부분을 while loop 분으로 채워짐
SC: O(n) => Set 사용
*/
var longestConsecutive = function (nums) {
const numsSet = new Set(nums);
let seq = 0;

for (num of numsSet) {
if (numsSet.has(num - 1)) continue;

let next = num + 1;
let currentSeq = 1;

while (numsSet.has(next)) {
currentSeq++;
next++;
}

seq = Math.max(seq, currentSeq);
}

return seq;
};

/*
memory out
*/
// var longestConsecutive = function(nums) {
// if (nums.length <= 1) return nums.length;

// const dedupeNums = new Set(nums);

// let maxValue = -Infinity;
// let minValue = Infinity;
// dedupeNums.forEach((num) => {
// maxValue = Math.max(maxValue, num);
// minValue = Math.min(minValue, num);
// });

// const markers = Array.from({ length: maxValue - minValue + 1 }, () => false);
// let maxSequence = 0;
// let currentSequence = 0;

// dedupeNums.forEach((num) => {
// markers[num - minValue] = true;
// });

// for (let i = 0; i < markers.length; i++) {
// if (markers[i]) currentSequence++;
// else {
// maxSequence = Math.max(maxSequence, currentSequence);
// currentSequence = 0;
// }
// }

// return Math.max(maxSequence, currentSequence);
// };
52 changes: 52 additions & 0 deletions top-k-frequent-elements/togo26.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* @param {number[]} nums
* @param {number} k
* @return {number[]}
*/

/*
TC: O(nlogn) -> sort
SC: O(n) => numsCount 생성
*/
var topKFrequent = function (nums, k) {
const numsCount = nums.reduce((acc, cur) => {
acc[cur] = acc[cur] + 1 || 1;
return acc;
}, {});

const frequecyOrder = Object.entries(numsCount)
.sort(([, a], [, b]) => b - a)
.map(([k, v]) => [Number(k), v]);

const result = [];

for (let i = 0; i < k; i++) result.push(frequecyOrder[i][0]);

return result;
};

/*
TC: O(n) -> frequency bucket index로 활용
SC: O(n)
*/
var topKFrequent = function (nums, k) {
const numsCount = nums.reduce((acc, cur) => {
acc[cur] = acc[cur] + 1 || 1;
return acc;
}, {});

const bucket = [];
Object.entries(numsCount).forEach(([num, freq]) => {
if (!bucket[freq]) bucket[freq] = [];
bucket[freq].push(Number(num));
});

const result = [];
for (let i = bucket.length - 1; i >= 0 && result.length < k; i--) {
if (Array.isArray(bucket[i])) {
result.push(...bucket[i]);
}
}

return result;
};
67 changes: 67 additions & 0 deletions two-sum/togo26.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/**
* @param {number[]} nums
* @param {number} target
* @return {number[]}
*/

/*
TC: O(n)
SC: O(n) -> Map 사용
*/

var twoSum = function (nums, target) {
const map = new Map();
for (let i = 0; i < nums.length; i++) {
const complement = target - nums[i];
if (map.has(complement)) return [map.get(complement), i];
map.set(nums[i], i);
}
};

/*
With two points
TC: O(nlogn) -> sort 사용
SC: O(n) -> origin index 배열 생성
*/

var twoSum = function (nums, target) {
const numsWithOriginIndex = nums.map((num, i) => [num, i]);
numsWithOriginIndex.sort(([a], [b]) => a - b);

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

while (left < right) {
const [leftValue, leftIndex] = numsWithOriginIndex[left];
const [rightValue, rightIndex] = numsWithOriginIndex[right];
const sum = leftValue + rightValue;

if (sum === target) {
result = [leftIndex, rightIndex];
break;
}

if (sum > target) right--;
else left++;
}

return result;
};

/*
Brute force
TC: O(n^2)
SC: O(1)
*/

var twoSum = function (nums, target) {
for (let i = 0; i < nums.length; i++) {
for (let j = i + 1; j < nums.length; j++) {
if (nums[i] + nums[j] === target) {
return [i, j];
}
}
}
return result;
};
Loading