diff --git a/3sum/uraflower.js b/3sum/uraflower.js new file mode 100644 index 000000000..8a7a86c99 --- /dev/null +++ b/3sum/uraflower.js @@ -0,0 +1,35 @@ +/** + * 주어진 배열 중 세 원소의 합이 0인 고유한 경우를 반환하는 함수 + * @param {number[]} nums + * @return {number[][]} + */ +const threeSum = function(nums) { + const answer = []; + const sorted = nums.toSorted((a, b) => Number(a) - Number(b)); + + for (let i = 0; i < sorted.length; i++) { + if (i > 0 && sorted[i] === sorted[i - 1]) continue; + + let left = i + 1; + let right = sorted.length - 1; + while (left < right) { + const sum = sorted[i] + sorted[left] + sorted[right]; + + if (sum > 0) right--; + else if (sum < 0) left++; + else { + answer.push([sorted[i], sorted[left], sorted[right]]); + right--; + + // 중복 방지 + while (sorted[left] === sorted[left + 1] && left < right) left++; + while (sorted[right] === sorted[right + 1] && left < right) right--; + } + } + } + + return answer; +}; + +// 시간복잡도: O(n^2) +// 공간복잡도: O(n) diff --git a/climbing-stairs/uraflower.js b/climbing-stairs/uraflower.js new file mode 100644 index 000000000..3dcece680 --- /dev/null +++ b/climbing-stairs/uraflower.js @@ -0,0 +1,23 @@ +/** + * 한 칸 또는 두 칸씩 n개의 계단을 오르는 방법의 가짓수를 반환하는 함수 + * @param {number} n + * @return {number} + */ +const climbStairs = function(n) { + const steps = Array.from({length: n + 1}).fill(0); + + for (let i = 1; i <= n; i++) { + if (i === 1) { + steps[i] = 1; + } else if (i === 2) { + steps[i] = 2; + } else { + steps[i] = steps[i-1] + steps[i-2]; + } + } + + return steps[n]; +}; + +// 시간복잡도: O(n) +// 공간복잡도: O(n) diff --git a/product-of-array-except-self/uraflower.js b/product-of-array-except-self/uraflower.js new file mode 100644 index 000000000..151a43e77 --- /dev/null +++ b/product-of-array-except-self/uraflower.js @@ -0,0 +1,19 @@ +/** + * 주어진 배열에서 자기 자신을 제외하고 나머지 원소를 곱한 값으로 구성된 배열을 반환하는 함수 + * @param {number[]} nums + * @return {number[]} + */ +const productExceptSelf = function(nums) { + const dp1 = []; // left to right + const dp2 = []; // right to left + + for (let i = 0, j = nums.length - 1; i < nums.length; i++, j--) { + dp1[i] = (dp1[i-1] ?? 1) * nums[i]; + dp2[j] = (dp2[j+1] ?? 1) * nums[j]; + } + + return nums.map((_, i) => (dp1[i-1] ?? 1) * (dp2[i+1] ?? 1)); +}; + +// 시간복잡도: O(n) +// 공간복잡도: O(n) --> dp 배열을 하나만 쓰는 방식으로 개선할 수 있을 듯 diff --git a/valid-anagram/uraflower.js b/valid-anagram/uraflower.js new file mode 100644 index 000000000..0a4a7b5cd --- /dev/null +++ b/valid-anagram/uraflower.js @@ -0,0 +1,27 @@ +/** + * 두 문자열이 애너그램인지 여부를 반환하는 함수 + * @param {string} s + * @param {string} t + * @return {boolean} + */ +const isAnagram = function (s, t) { + if (s.length !== t.length) return false; + + const counter = Array.from(s).reduce((counter, char) => { + counter[char] = counter[char] + 1 || 1; + return counter; + }, {}); + + for (let char of t) { + if (!counter[char] || counter[char] === 0) { + return false; + } + + counter[char] -= 1; + } + + return true; +}; + +// 시간복잡도: O(n) +// 공간복잡도: O(n) diff --git a/validate-binary-search-tree/uraflower.js b/validate-binary-search-tree/uraflower.js new file mode 100644 index 000000000..2b87f8b63 --- /dev/null +++ b/validate-binary-search-tree/uraflower.js @@ -0,0 +1,56 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * 이진 탐색 트리(BST)인지 확인하는 함수 + * @param {TreeNode} root + * @return {boolean} + */ + +///////////////////////// 1 /////////////////////////// +// inorder traversal한 결과를 배열에 담아 오름차순 정렬인지 확인 +const isValidBST = function(root) { + const inorder = []; + inorderTraversal(root, inorder); + + return inorder.every((val, i, arr) => i === 0 || arr[i-1] < val); +}; + +function inorderTraversal(current, result) { + if (current.left) { + inorderTraversal(current.left, result); + } + + result.push(current.val); + + if (current.right) { + inorderTraversal(current.right, result); + } +} + +///////////////////////// 2 /////////////////////////// +// inorder traversal하면서 바로 직전에 순회한 값이 현재 값보다 작은지 확인 (=오름차순인지 바로바로 확인) +const isValidBST = function(root) { + let prev = -Infinity; + + function inorder(node) { + if (!node) return true; + + if (!inorder(node.left)) return false; + + if (node.val <= prev) return false; + prev = node.val; + + return inorder(node.right); + } + + return inorder(root); +}; + +// 시간복잡도: O(n) +// 공간복잡도: O(n) (재귀 스택 == 트리 높이. 최악의 경우 편향 트리일 때 높이는 n)