diff --git a/contains-duplicate/reach0908.js b/contains-duplicate/reach0908.js new file mode 100644 index 000000000..7ff8f7607 --- /dev/null +++ b/contains-duplicate/reach0908.js @@ -0,0 +1,19 @@ +/** + * @description + * time complexity: O(n) + * space complexity: O(n) + * 풀이 방법: + * - 주어진 배열을 순회하며 해쉬테이블을 구성하고 해쉬 테이블에 이미 값이 있는 경우 early return 을 통해 중복됨을 반환 + * @param {number[]} nums + * @return {boolean} + */ +const containsDuplicate = function (nums) { + const hashTable = new Set(); + for (let i = 0; i < nums.length; i++) { + if (hashTable.has(nums[i])) { + return true; + } + hashTable.set(nums[i], i); + } + return false; +}; diff --git a/house-robber/reach0908.js b/house-robber/reach0908.js new file mode 100644 index 000000000..d3d7f2d90 --- /dev/null +++ b/house-robber/reach0908.js @@ -0,0 +1,46 @@ +/** + * @description + * time complexity: O(2^n) + * space complexity: O(n) + * 풀이 실패 + * 풀이 방법: 선택한 경우와 선택하지 않은 경우를 재귀적으로 호출하여 최대값을 반환한다. + * @param {number[]} nums + * @return {number} + */ +const rob = function (nums) { + console.log(nums); + if (nums.length === 0) return 0; + if (nums.length === 1) return nums[0]; + if (nums.length === 2) return Math.max(nums[0], nums[1]); + + // 선택한 경우 + const selected = nums[0] + rob(nums.slice(2)); + // 선택하지 않은 경우 + const unselected = rob(nums.slice(1)); + + const max = Math.max(selected, unselected); + + return max; +}; + +/** + * @description + * time complexity: O(n) + * space complexity: O(n) + * runtime: 100ms + * 풀이 방법: 위 풀이가 타임아웃이 남, DP로 풀어야함을 인지 후 풀이 방법 변경 + * @param {number[]} nums + * @return {number} + */ +const robSolution2 = function (nums) { + const dp = new Array(nums.length).fill(0); + + dp[0] = nums[0]; + dp[1] = Math.max(nums[0], nums[1]); + + for (let i = 2; i < nums.length; i += 1) { + dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]); + } + + return dp[nums.length - 1]; +}; diff --git a/longest-consecutive-sequence/reach0908.js b/longest-consecutive-sequence/reach0908.js new file mode 100644 index 000000000..762d188df --- /dev/null +++ b/longest-consecutive-sequence/reach0908.js @@ -0,0 +1,68 @@ +/** + * @description + * time complexity: O(n log n) + * space complexity: O(n) + * runtime: 57ms + * 풀이 방법: 중복을 제거하고 정렬한 다음에 연속된 숫자의 개수를 카운트하여 최대값을 반환한다. + * @param {number[]} nums + * @return {number} + */ +const longestConsecutive = function (nums) { + if (nums.length === 0) return 0; + const sortedNums = [...new Set(nums)].sort((a, b) => a - b); + + let maxConsecutiveCount = 1; + let currentConsecutiveCount = 1; + + for (let i = 1; i < sortedNums.length; i += 1) { + if (sortedNums[i] === sortedNums[i - 1] + 1) { + currentConsecutiveCount += 1; + } else { + currentConsecutiveCount = 1; + } + + maxConsecutiveCount = Math.max( + maxConsecutiveCount, + currentConsecutiveCount + ); + } + + return maxConsecutiveCount; +}; + +/** + * @description + * time complexity: O(n) + * space complexity: O(n) + * runtime: 36ms + * 풀이 방법: 중복을 제거하고 Set을 사용하여 O(1) 조회 가능하도록 한 다음에 연속된 숫자의 개수를 카운트하여 최대값을 반환한다. + * @param {number[]} nums + * @return {number} + */ +const longestConsecutive2 = function (nums) { + if (nums.length === 0) return 0; + + // Set을 사용하여 O(1) 조회 가능 + const numSet = new Set(nums); + let maxLength = 0; + + for (const num of numSet) { + // 현재 숫자가 연속 수열의 시작점인지 확인 + // num-1이 존재하지 않으면 num이 시작점 + if (!numSet.has(num - 1)) { + let currentNum = num; + let currentLength = 1; + + // 연속된 다음 숫자들이 존재하는 동안 계속 탐색 + while (numSet.has(currentNum + 1)) { + currentNum += 1; + currentLength += 1; + } + + // 최대 길이 업데이트 + maxLength = Math.max(maxLength, currentLength); + } + } + + return maxLength; +}; diff --git a/top-k-frequent-elements/reach0908.js b/top-k-frequent-elements/reach0908.js new file mode 100644 index 000000000..800fe0f4f --- /dev/null +++ b/top-k-frequent-elements/reach0908.js @@ -0,0 +1,29 @@ +/** + * @description + * time complexity: O(n log n) + * space complexity: O(n) + * runtime: 3ms + * 풀이 방법: + * 해시맵을 통해 각 숫자의 빈도수를 계산 + * 해시맵을 정렬하여 빈도수가 높은 순서대로 정렬 + * 정렬된 배열을 k만큼 짤라서 반환 + * @param {number[]} nums + * @param {number} k + * @return {number[]} + */ +const topKFrequent = function (nums, k) { + const hashMap = new Map(); + + for (const num of nums) { + if (hashMap.has(num)) { + hashMap.set(num, hashMap.get(num) + 1); + } else { + hashMap.set(num, 1); + } + } + + return Array.from(hashMap.entries()) + .sort((a, b) => b[1] - a[1]) + .slice(0, k) + .map(([num]) => num); +}; diff --git a/two-sum/reach0908.js b/two-sum/reach0908.js new file mode 100644 index 000000000..1c315f4d1 --- /dev/null +++ b/two-sum/reach0908.js @@ -0,0 +1,55 @@ +/** + * @description + * time complexity: O(n^2) + * space complexity: O(1) + * 풀이 방법: + * 카운터를 통해 반복문 돌기 + * 겉으로는 반복문이 한개 같아보이지만 이중반복문이다. + * @param {number[]} nums + * @param {number} target + * @return {number[]} + */ +const twoSumSoluton1 = function (nums, target) { + let left = 0; + let right = 1; + while (left < nums.length - 1) { + const sum = nums[left] + nums[right]; + if (sum === target) { + return [left, right]; + } + + if (right < nums.length - 1) { + right += 1; + } else { + left += 1; + right = left + 1; + } + } +}; + +/** + * @description + * 다른 사람들의 풀이를 보고 개선한 솔루션 + * time complexity: O(n) + * space complexity: O(n) + * 풀이 방법: + * 이전 값들 중에 원하는 값이 있는지만 확인 후 추출, 시간복잡도를 크게 감소시킴 + * 하지만 해쉬맵을 만들어야해서 공간복잡도는 O(n)으로 변경 + * @param {number[]} nums + * @param {number} target + * @return {number[]} + */ +const twoSumSoluton2 = function (nums, target) { + const hashMap = new Map(); + + for (let i = 0; i < nums.length; i += 1) { + const calculatedTarget = target - nums[i]; + if (hashMap.has(calculatedTarget)) { + return [i, hashMap.get(calculatedTarget)]; + } + + hashMap.set(nums[i], i); + } + + return []; +};