diff --git a/climbing-stairs/naringst.js b/climbing-stairs/naringst.js new file mode 100644 index 000000000..1b4e9e1ea --- /dev/null +++ b/climbing-stairs/naringst.js @@ -0,0 +1,28 @@ +/** + * @param {number} n + * @return {number} + */ +/** + * Note: DP + * 결국 1개 전의 값에서 1칸을 더 가거나, 2개 전의 값에서 2칸을 더 가는 경우의 수가 생긴다. + * 1일때에는 1칸을 가는 방법의 경우 뿐이지만, 2일때에는 0칸 가는 것에서 2칸을 가거나 1칸을 가는 것에서 1칸을 더 갈 수 있다. + * 3일 때에는 1까지 갔을 경우에서 2칸을 더 가거나, 2까지 갔을 경우에서 1칸을 더 가면 되니까 1까지 갔을 경우의 수 + 2까지 갔을 경우의 수 + * + * + * Runtime: 41ms, Memory: 48.95MB + * Time complexity: O(n) + * Space complexity: O(n) + * + */ + +var climbStairs = function (n) { + const dp = Array(n).fill(0); + dp[1] = 1; + dp[2] = 2; + + for (let i = 3; i < n + 1; i++) { + dp[i] = dp[i - 2] + dp[i - 1]; + } + + return dp[n]; +}; diff --git a/coin-change/naringst.js b/coin-change/naringst.js new file mode 100644 index 000000000..89887d38a --- /dev/null +++ b/coin-change/naringst.js @@ -0,0 +1,61 @@ +/** + * @param {number[]} coins + * @param {number} amount + * @return {number} + */ + +/** + * combination sum 풀이를 활용했지만 amount가 커서 + * time limit exceeded + * */ + +var coinChange = function (coins, amount) { + let answer = []; + let coins_desc = coins.reverse(); + + if (amount === 0) return 0; + + function permute(arr = [], sum = 0, index = 0) { + if (sum > amount) return; + // 같은 경우에만 result에 담기 + if (sum === amount) { + if (answer.length === 0) { + answer = [...arr]; + } else { + if (arr.length < answer.length) { + answer = [...arr]; + } else { + return answer.length; + } + } + } + for (let i = index; i < coins.length; i++) { + // target보다 합이 작으면 재귀적으로 해당 값을 arr에 넣고, sum에 추가 + permute([...arr, coins_desc[i]], sum + coins_desc[i], i); + } + } + permute(); + return answer.length === 0 ? -1 : answer.length; +}; + +/** + * 풀이(참고): combination sum을 dp로 풀려고 했었는데, 사실 이 문제가 dp로 풀어야 하는 문제 + */ + +/** + * @param {number[]} coins + * @param {number} amount + * @return {number} + */ +var coinChange = function (coins, amount) { + let dp = Array.from({ length: amount + 1 }, () => Infinity); + dp[0] = 0; + + for (const coin of coins) { + for (let i = coin; i <= amount; i += 1) { + dp[i] = Math.min(dp[i], dp[i - coin] + 1); + } + } + + return dp[amount] === Infinity ? -1 : dp[amount]; +}; diff --git a/combination-sum/naringst.js b/combination-sum/naringst.js new file mode 100644 index 000000000..b30d73ab1 --- /dev/null +++ b/combination-sum/naringst.js @@ -0,0 +1,49 @@ +/** + * NOTE: + * 1. dp를 사용하려고 했으나 시간초과 + * 2. 재귀를 활용해 가능한 한 모든 중복조합을 구해서 계산하기 + * + */ + +// 1번 시도 + +var combinationSum = function (candidates, target) { + const dp = Array(target + 1).fill(1); + + for (let i = 2; i < candidates.length; i++) { + dp[i] = 1; + for (let j = 1 < Math.floor(i / 2); ; j++) { + dp[i] += dp[j] * dp[i - j]; + } + // ...이미 시간초과 + } +}; + +// 2번 풀이(참고) +// 재귀를 활용해 한 값이 중복으로 더해지는 부분을 처리 -> target보다 클때까지 재귀 +// for 문을 활용해 candidates의 모든 값을 순회 +// +/** + * Runtime: 78ms, Memory: 59.13MB + * Time complexity: O(n * target/n) => O(2^n * k) by gpt (k: 조합의 길이) + * Space complexity: O(n * target/n) => O(target) + O(2^n * k ) by gpt + * + */ + +var combinationSum = function (candidates, target) { + const result = []; + + function permute(arr = [], sum = 0, idx = 0) { + // target보다 합이 크면 리턴 + if (sum > target) return; + // 같은 경우에만 result에 담기 + if (sum === target) result.push(arr); + + for (let i = idx; i < candidates.length; i++) { + // target보다 합이 작으면 재귀적으로 해당 값을 arr에 넣고, sum에 추가 + permute([...arr, candidates[i]], sum + candidates[i], i); + } + } + permute(); + return result; +}; diff --git a/product-of-array-except-self/naringst.js b/product-of-array-except-self/naringst.js new file mode 100644 index 000000000..ef275817a --- /dev/null +++ b/product-of-array-except-self/naringst.js @@ -0,0 +1,74 @@ +/** + * @param {number[]} nums + * @return {number[]} + */ + +/** + * Runtime: 124ms, Memory: 65.06MB + * Time complexity: O(n^2) + * Space complexity: O(n) + * -> answer 배열에 O(n) + * -> splicedArr 배열에 O(n) + */ + +var productExceptSelf = function (nums) { + const totalProduct = nums.reduce((total, current) => total * current, 1); + const answer = Array(nums.length).fill(0); + + for (let i = 0; i < nums.length; i++) { + answer[i] = totalProduct / nums[i]; + if (nums[i] === 0) { + const splicedArr = nums.filter(function (_, index) { + return index !== i; + }); + answer[i] = splicedArr.reduce((total, current) => total * current, 1); + } + } + + return answer; +}; + +/** + * @param {number[]} nums + * @return {number[]} + */ + +/** + * 위의 풀이는 0일 때마다 순회를 해야 하기 때문에 해당 부분을 0의 개수를 세어 처리하도록 변경한 풀이 + + * Runtime: 109ms, Memory: 63.45MB + * Time complexity: O(n) + * Space complexity: O(n) + + */ +var productExceptSelf = function (nums) { + let totalProduct = 1; + let zeroCount = 0; + const answer = Array(nums.length).fill(0); + + for (let numIndex = 0; numIndex < nums.length; numIndex++) { + if (nums[numIndex] === 0) { + zeroCount += 1; + } else { + totalProduct *= nums[numIndex]; + } + } + + for (let i = 0; i < nums.length; i++) { + if (nums[i] === 0) { + if (zeroCount - 1 > 0) { + answer[i] = 0; + } else { + answer[i] = totalProduct; + } + } else { + if (zeroCount > 0) { + answer[i] = 0; + } else { + answer[i] = totalProduct / nums[i]; + } + } + } + + return answer; +}; diff --git a/two-sum/naringst.js b/two-sum/naringst.js new file mode 100644 index 000000000..6999b5358 --- /dev/null +++ b/two-sum/naringst.js @@ -0,0 +1,49 @@ +/** + * @param {number[]} nums + * @param {number} target + * @return {number[]} + */ + +/** + * Runtime: 107ms, Memory: 49.52MB + * Time complexity: O(n^2) + * Space complexity: O(n^2) + * + * **/ + +var twoSum = function (nums, target) { + const answer = []; + for (let i = 0; i < nums.length - 1; i++) { + for (let j = i + 1; j < nums.length; j++) { + if (nums[i] + nums[j] === target) { + return [i, j]; + } + } + } +}; + +/** + * @param {number[]} nums + * @param {number} target + * @return {number[]} + */ + +/** + * 다른 풀이: two의 sum 이니까 target - 현재 값을 한 뒤, 나머지 값이 배열에 있는지 찾는 방법. + * 이 과정에서 해시맵을 사용해서 target - 현재 값이 map 에 존재하면 return + * 없다면 map에 나머지 값과 그에 해당하는 인덱스를 추가한다. + * 그럼 추후에는 나머지 값을 map에서 O(1)로 찾기만 하면 된다. + * + * Runtime: 49ms, Memory: 49.52MB + * Time complexity: O(n) + * Space complexity: O(n) + * **/ + +var twoSum = function (nums, target) { + let map = new Map(); + + for (i = 0; i < nums.length; i++) { + if (map.has(target - nums[i])) return [map.get(target - nums[i]), i]; + map.set(nums[i], i); + } +};