From 1fca64032f876fba1006c8ffc3982c2c895d3657 Mon Sep 17 00:00:00 2001 From: Carpe-sehee Date: Thu, 5 Mar 2026 13:14:01 +0900 Subject: [PATCH 1/4] sadie100: contains-duplicate solution --- contains-duplicate/sadie100.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 contains-duplicate/sadie100.ts diff --git a/contains-duplicate/sadie100.ts b/contains-duplicate/sadie100.ts new file mode 100644 index 000000000..74490de1f --- /dev/null +++ b/contains-duplicate/sadie100.ts @@ -0,0 +1,19 @@ +/** +풀이 +- JS 집합 자료구조인 Set을 활용합니다. Set은 중복값이 들어올 경우 제거되어 고유한 값들만 갖는 특성이 있습니다. +- nums를 Set으로 바꾸고 두 데이터의 length(Set의 경우 size 접근자 사용)를 비교합니다. + - 다를 경우 : Set에서 중복값이 제거된 경우이므로 true를 반환합니다. + - 같을 경우 : 중복값이 없던 경우이므로 false를 반환합니다. + +Big O +- Time Complexity: O(N) (N은 nums의 길이) + new Set(nums)를 만드는 과정에서 배열의 모든 원소를 순회하며 Set에 삽입합니다. (삽입 평균 시간 O(1)) + numSet.size 및 nums.length는 각각 O(1)이므로 총 O(N)의 시간복잡도를 갖습니다. +- Space Complexity: O(N) + Set에 최대 n개의 요소가 저장되므로 O(N)의 공간복잡도를 갖습니다. + */ + +function containsDuplicate(nums: number[]): boolean { + const numSet = new Set(nums) + return numSet.size !== nums.length +} From 6629a0e90b0336f696cd1ca8ef6dc2dd3ec69fc4 Mon Sep 17 00:00:00 2001 From: sadie100 <03sadie@gmail.com> Date: Fri, 6 Mar 2026 13:56:52 +0900 Subject: [PATCH 2/4] sadie100: two sum solution --- two-sum/sadie100.ts | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 two-sum/sadie100.ts diff --git a/two-sum/sadie100.ts b/two-sum/sadie100.ts new file mode 100644 index 000000000..14f755451 --- /dev/null +++ b/two-sum/sadie100.ts @@ -0,0 +1,33 @@ +/* +풀이 +nums를 값과 index가 있는 객체 배열 newNums로 재정의한다 +newNums를 값 오름차순으로 정렬하고 두 포인터 start, end를 둔다 +nums[start] + nums[end]가 target보다 작으면 start+1하고, target보다 크면 end-1한다. 같으면 nums[start]과 nums[end]의 오리진 index를 리턴한다. +만약 start>=end가 되면 빈 배열을 리턴한다 + +시간복잡도 +O(nLogN) - 정렬. 포인터 순회는 O(N)이므로 최종적으로 O(nLogN) + +공간복잡도 +O(N) : newNums 배열 +*/ + +function twoSum(nums: number[], target: number): number[] { + const newNums = nums.map((value, idx) => ({ value, idx })) + const sortedNums = newNums.sort((a, b) => a.value - b.value) + let start = 0 + let end = nums.length - 1 + + while (start < end) { + const total = sortedNums[start].value + sortedNums[end].value + if (total === target) { + return [sortedNums[start].idx, sortedNums[end].idx] + } else if (total > target) { + end -= 1 + } else { + start += 1 + } + } + + return [] +} From ea5ed1f815e3feac26ee0e91cba21b6b8f1fcbef Mon Sep 17 00:00:00 2001 From: sadie100 <03sadie@gmail.com> Date: Fri, 6 Mar 2026 14:12:59 +0900 Subject: [PATCH 3/4] =?UTF-8?q?sadie100:=20two=20sum=20solution=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- two-sum/sadie100.ts | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/two-sum/sadie100.ts b/two-sum/sadie100.ts index 14f755451..b44e079a0 100644 --- a/two-sum/sadie100.ts +++ b/two-sum/sadie100.ts @@ -1,31 +1,24 @@ /* 풀이 -nums를 값과 index가 있는 객체 배열 newNums로 재정의한다 -newNums를 값 오름차순으로 정렬하고 두 포인터 start, end를 둔다 -nums[start] + nums[end]가 target보다 작으면 start+1하고, target보다 크면 end-1한다. 같으면 nums[start]과 nums[end]의 오리진 index를 리턴한다. -만약 start>=end가 되면 빈 배열을 리턴한다 +해시맵을 이용해 현재 값의 보수(target - num)가 이미 등장했는지 확인한다. + 시간복잡도 -O(nLogN) - 정렬. 포인터 순회는 O(N)이므로 최종적으로 O(nLogN) +O(N) - nums 순회 공간복잡도 -O(N) : newNums 배열 +O(N) - numObj 생성 */ function twoSum(nums: number[], target: number): number[] { - const newNums = nums.map((value, idx) => ({ value, idx })) - const sortedNums = newNums.sort((a, b) => a.value - b.value) - let start = 0 - let end = nums.length - 1 + const numObj: { [key: number]: number } = {} - while (start < end) { - const total = sortedNums[start].value + sortedNums[end].value - if (total === target) { - return [sortedNums[start].idx, sortedNums[end].idx] - } else if (total > target) { - end -= 1 + for (let i = 0; i < nums.length; i++) { + const num = nums[i] + if (target - num in numObj) { + return [i, numObj[target - num]] } else { - start += 1 + numObj[num] = i } } From 8893664846812e7456c99c3119c8b1466e5fb663 Mon Sep 17 00:00:00 2001 From: sadie100 <03sadie@gmail.com> Date: Sat, 7 Mar 2026 17:28:01 +0900 Subject: [PATCH 4/4] =?UTF-8?q?sadie100:=20Week=201=203=EB=AC=B8=EC=A0=9C?= =?UTF-8?q?=20=ED=92=80=EC=9D=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- house-robber/sadie100.ts | 25 ++++++++++++++++++++ longest-consecutive-sequence/sadie100.ts | 30 ++++++++++++++++++++++++ top-k-frequent-elements/sadie100.ts | 27 +++++++++++++++++++++ 3 files changed, 82 insertions(+) create mode 100644 house-robber/sadie100.ts create mode 100644 longest-consecutive-sequence/sadie100.ts create mode 100644 top-k-frequent-elements/sadie100.ts diff --git a/house-robber/sadie100.ts b/house-robber/sadie100.ts new file mode 100644 index 000000000..21e7a6cbc --- /dev/null +++ b/house-robber/sadie100.ts @@ -0,0 +1,25 @@ +/** +dp 배열을 만들고 각 원소 순서에서 최대의 값을 계산, 리턴한다 + +시간복잡도 +O(N) : 단일 순회 + +공간복잡도 +O(N) : dp 배열 + */ + +function rob(nums: number[]): number { + const dp = [] + + for (let i = 0; i < nums.length; i++) { + if (i < 1) { + dp[i] = nums[i] + } else if (i < 2) { + dp[i] = Math.max(dp[i - 1], nums[i]) + } else { + dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1]) + } + } + + return dp.at(-1) +} diff --git a/longest-consecutive-sequence/sadie100.ts b/longest-consecutive-sequence/sadie100.ts new file mode 100644 index 000000000..1e8eb33d0 --- /dev/null +++ b/longest-consecutive-sequence/sadie100.ts @@ -0,0 +1,30 @@ +/** +nums를 Set으로 만들어서 중복을 제거하고 순회하면서 시작점(n-1이 Set에 없는 수)을 찾아 연속된 수를 찾아가며 length를 계산한다. +시작점이 아닌 num(set에 num-1이 있는 경우)는 순회하지 않는다. + +시간복잡도 +O(N) : 이중 반복문이지만 시작점에서만 탐색하므로 깊은 중복 순회가 없음 + */ + +function longestConsecutive(nums: number[]): number { + if (nums.length === 0) return 0 + const numSet = new Set(nums) + let result = 1 + + for (let num of numSet) { + if (numSet.has(num - 1)) { + continue + } + + let next = num + 1 + let count = 1 + while (numSet.has(next)) { + count += 1 + next += 1 + } + + result = Math.max(result, count) + } + + return result +} diff --git a/top-k-frequent-elements/sadie100.ts b/top-k-frequent-elements/sadie100.ts new file mode 100644 index 000000000..4d3c40f27 --- /dev/null +++ b/top-k-frequent-elements/sadie100.ts @@ -0,0 +1,27 @@ +/** +nums를 순회하며 {[num]: 등장횟수} 형태의 데이터로 바꾸고, 순회가 끝난후 +해당 데이터를 등장횟수 기준으로 내림차순 정렬하여 상위 k개를 리턴한다 + +O(N) +시간복잡도 : O(NlogN) +nums 순회 - O(N), 객체 배열화 - O(N), 정렬 - O(NLogN) 도합 O(NLogN) + */ + +function topKFrequent(nums: number[], k: number): number[] { + const countObj: Record = {} + + for (let num of nums) { + if (num in countObj) { + countObj[num] += 1 + } else { + countObj[num] = 1 + } + } + + const countArr = Object.entries(countObj) + .sort((a, b) => b[1] - a[1]) + .map(([num, cnt]) => Number(num)) + .filter((val, idx) => idx < k) + + return countArr +}