Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
26 changes: 26 additions & 0 deletions contains-duplicate/suKyoung.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// 1번째 풀이 (hashMap)
function containsDuplicate1(nums: number[]): boolean {
const seen: Record<number, boolean> = {};

const isDuplicate = nums.some((num) => {
if (seen[num]) return true;
seen[num] = true;
return false;
});

return isDuplicate;
}

// 2번째 풀이(Set)
function containsDuplicate2(nums: number[]): boolean {
const set = new Set();

for (const num of nums) {
if (set.has(num)) {
return true;
}
set.add(num);
}

return false;
}
46 changes: 46 additions & 0 deletions longest-consecutive-sequence/suKyoung.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// 1번풀이
function longestConsecutive2(nums: number[]): number {
if (nums.length === 0) return 0;

const copiedNums = [...new Set(nums)].sort((a, b) => a - b);

let max = 1; // 지금까지 나왔던 가장 긴 연속 수열의 길이
let count = 1; // 현재 연속 수열의 길이

for (let i = 1; i < copiedNums.length; i++) {
const prev = copiedNums[i - 1];
const current = copiedNums[i];

if (current === prev + 1) {
count++;
max = Math.max(max, count);
} else {
count = 1;
}
}

return max;
}

// 2번풀이 (hashSet)
function longestConsecutive(nums: number[]): number {
const numSet = new Set(nums);
let max = 0;

for (const num of numSet) {
// 수열의 시작점인 경우만 탐색
if (!numSet.has(num - 1)) {
let current = num;
let count = 1;

while (numSet.has(current + 1)) {
current++;
count++;
}

max = Math.max(max, count);
}
}

return max;
}
105 changes: 105 additions & 0 deletions top-k-frequent-elements/suKyoung.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// 1번풀이 (brute force)
type FrequencyMap = Record<number, number>;

function topKFrequentCountDown(nums: number[], k: number): number[] {
const freqMap = buildFrequencyMap1(nums);
return pickTopKDescending(freqMap, k);
}

function buildFrequencyMap1(nums: number[]): FrequencyMap {
const map: FrequencyMap = {};
for (const num of nums) {
map[num] = (map[num] || 0) + 1;
}
return map;
}

function pickTopKDescending(freqMap: FrequencyMap, k: number): number[] {
const result: number[] = [];
const entries = Object.entries(freqMap).map(([key, value]) => [
Number(key),
value,
]);
let currentFrequent = Math.max(...entries.map(([_, freq]) => freq));

while (result.length < k && currentFrequent > 0) {
for (const [num, freq] of entries) {
if (freq === currentFrequent) {
result.push(num);
if (result.length === k) break;
}
}
currentFrequent--;
}

return result;
}


// 2번풀이(Bucket Sort)
function topKFrequent(nums: number[], k: number): number[] {
const frequencyMap = buildFrequencyMap2(nums);
const frequencyBuckets = buildFrequencyBuckets(nums.length, frequencyMap);

return collectTopKFrequent(frequencyBuckets, k);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

알고리즘 풀이를 할 때에는 함수를 잘 분리하지 않게 되던데... 함수를 잘 분리해 주셔서 덕분에 긴 흐름을 잘 이해할 수 있었습니다 👍👍


function buildFrequencyMap2(nums: number[]): FrequencyMap {
const freqMap: FrequencyMap = {};
for (const num of nums) {
freqMap[num] = (freqMap[num] || 0) + 1;
}
return freqMap;
}

function buildFrequencyBuckets(
size: number,
freqMap: FrequencyMap
): number[][] {
const buckets: number[][] = Array(size + 1).fill(null).map(() => []);

for (const [numStr, frequent] of Object.entries(freqMap)) {
const num = Number(numStr);
buckets[frequent].push(num);
}

return buckets;
}

function collectTopKFrequent(buckets: number[][], k: number): number[] {
const result: number[] = [];

for (let i = buckets.length - 1; i >= 0 && result.length < k; i--) {
for (const num of buckets[i]) {
result.push(num);
if (result.length === k) break;
}
}

return result;
}


// 3번풀이 (MinHeap)
function topKFrequentHeap(nums: number[], k: number): number[] {
const freqMap: Record<number, number> = {};

for (const num of nums) {
freqMap[num] = (freqMap[num] || 0) + 1;
}

const heap: [number, number][] = [];
for (const [numStr, frequent] of Object.entries(freqMap)) {
const num = Number(numStr);

heap.push([num, frequent]);
heap.sort((a, b) => a[1] - b[1]);

if (heap.length > k) {
heap.shift();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

여기서는 heap의 크기가 그렇게 크지 않아서 큰 영향은 없을 것 같지만,,,
shift 메서드는 제거한 뒤에 남은 원소들을 앞쪽으로 당기기 때문에 시간복잡도가 O(n)으로 크기가 큰 배열에서는 성능이 좋지 않은 메서드라고 알고 있어요! (참고 블로그)
오름차순이 아닌 내림차순으로 정렬한 뒤에 heap.pop()으로 뒤쪽 원소를 제거한다면 좀 더 빠르게 적게 등장한 원소를 제거할 수 있을 것 같아서 코멘트 남겨봅니당 ㅎㅎ

}

return heap.map(([num]) => num);
}

45 changes: 45 additions & 0 deletions two-sum/suKyoung.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// 1번째 풀이 (brute force)
function twoSum1(nums: number[], target: number): number[] {
for(let i = 0; i < nums.length; i++) {
for (let j = 1; j < nums.length; j++) {
const a = nums[i];
const b = nums[j];

if (a + b === target && i !== j) {
return [i, j];
}
}
}
return [];
};

// 2번째 풀이 (indexOf)
function twoSum2(nums: number[], target: number): number[] {
for (let i = 0; i < nums.length; i++) {
const j = target - nums[i];
const index = nums.indexOf(j);

if (nums.includes(j) && i !== index) {
return [i, index];
}
Copy link
Contributor

Choose a reason for hiding this comment

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

indexOf 메서드는 만약에 jnums에서 찾지 못하면 -1을 반환하는 것으로 알고 있어요! (mdn 참고)
nums.includes(j)를 조건문에서 한번 더 쓰게 되면 nums에서 원소를 찾는 연산이 중복이 되는 것 같아서...
indexOf 의 결과가 -1인지 확인해주는 방법을 써도 좋을 것 같아요!!

}
return [];
};

// 3번째 풀이 (HashMap)
function twoSum(nums: number[], target: number): number[] {
const map: Record<number, number> = {};

for (let i = 0; i < nums.length; i++) {
const complement = target - nums[i];

if (complement in map) {
const j = map[complement];
return [i, j];
} else {
map[nums[i]] = i;
}
}

return [];
};
Copy link
Contributor

Choose a reason for hiding this comment

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

지금 linelint에서 에러가 나고 있는데 답안 제출 가이드를 보니 파일 끝에 개행문자를 추가해야 한다고 해요!
two-sum이랑 top-k-frequent-elements 쪽 파일 끝 개행문자 추가해주시면 에러도 해결될 듯 합니다 ㅎㅎ

Loading