diff --git a/oris8/102_binary-tree-level-order-traversal.js b/oris8/102_binary-tree-level-order-traversal.js new file mode 100644 index 0000000..ef1f308 --- /dev/null +++ b/oris8/102_binary-tree-level-order-traversal.js @@ -0,0 +1,66 @@ +/** + * 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) + * } + * + * 102 / Binary Tree Level Order Traversal / Medium / 12m 8s + */ +/** + * @param {TreeNode} root + * @return {number[][]} + */ +/** + * 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) + * } + */ +/** + * @param {TreeNode} root + * @return {number[][]} + */ +var levelOrder = function (root) { + if (!root) return []; + + const result = []; + const queue = [root]; + + while (queue.length > 0) { + const levelSize = queue.length; + const currentLevel = []; + + for (let i = 0; i < levelSize; i++) { + const node = queue.shift(); + currentLevel.push(node.val); + + if (node.left) queue.push(node.left); + if (node.right) queue.push(node.right); + } + + result.push(currentLevel); + } + + return result; +}; + +// var levelOrder = function(root) { +// const result = []; + +// const traverse = (node, level) => { +// if (!node) return; +// if (result.length === level) { +// result.push([]); // 새로운 레벨 생성 +// } +// result[level].push(node.val); // 현재 레벨에 값 추가 +// traverse(node.left, level + 1); // 왼쪽 자식 탐색 +// traverse(node.right, level + 1); // 오른쪽 자식 탐색 +// }; + +// traverse(root, 0); +// return result; +// }; diff --git a/oris8/128_longest-consecutive-sequence.js b/oris8/128_longest-consecutive-sequence.js new file mode 100644 index 0000000..c7e1fe4 --- /dev/null +++ b/oris8/128_longest-consecutive-sequence.js @@ -0,0 +1,35 @@ +/** + * + * 128. Longest Consecutive Sequence + * Medium + * Topics + * Companies + * Given an unsorted array of integers nums, return the length of the longest consecutive elements sequence. + * + * You must write an algorithm that runs in O(n) time. + * @param {number[]} nums + * @return {number} + */ +var longestConsecutive = function (nums) { + // 중복되는 요소 허용, 빈 배열 허용 + if (nums.length === 0) return 0; + + const set = new Set(nums); + const sortedSet = Array.from(set).sort((a, b) => a - b); + + let maxSequenceLength = 1; + let currentSequence = [sortedSet[0]]; + + for (let i = 1; i < sortedSet.length; i++) { + const last = currentSequence.pop(); + if (last + 1 === sortedSet[i]) { + currentSequence.push(last); + currentSequence.push(sortedSet[i]); + } else { + currentSequence = [sortedSet[i]]; + } + maxSequenceLength = Math.max(maxSequenceLength, currentSequence.length); + } + + return maxSequenceLength; +}; diff --git a/oris8/150_evaluate-reverse-polish-notation.js b/oris8/150_evaluate-reverse-polish-notation.js new file mode 100644 index 0000000..57d3722 --- /dev/null +++ b/oris8/150_evaluate-reverse-polish-notation.js @@ -0,0 +1,29 @@ +/** + * + * 150 / Evaluate Reverse Polish Notation / Medium / 36m 44s + * + * @param {string[]} tokens + * @return {number} + */ +var evalRPN = function (tokens) { + const operators = { + "+": (a, b) => a + b, + "-": (a, b) => a - b, + "*": (a, b) => a * b, + "/": (a, b) => Math.trunc(a / b), + }; + + const stack = []; + + for (const token of tokens) { + if (operators?.[token]) { + const b = stack.pop(); + const a = stack.pop(); + stack.push(operators[token](a, b)); + } else { + stack.push(+token); + } + } + + return stack.pop(); +}; diff --git a/oris8/207_course-schedule.js b/oris8/207_course-schedule.js new file mode 100644 index 0000000..6aaaf3c --- /dev/null +++ b/oris8/207_course-schedule.js @@ -0,0 +1,50 @@ +// 207 / Course Schedule / Medium / - +/** + * @param {number} numCourses + * @param {number[][]} prerequisites + * @return {boolean} + */ + +/** + * @param {number} numCourses + * @param {number[][]} prerequisites + * @return {boolean} + */ +var canFinish = function (numCourses, prerequisites) { + const graph = new Map(); + + // 그래프 생성 + for (let i = 0; i < numCourses; i++) { + graph.set(i, []); + } + + for (const [course, prereq] of prerequisites) { + graph.get(prereq).push(course); + } + + // 방문 상태 관리 + const visited = new Set(); // 현재 DFS 방문 중인 노드 + const completed = new Set(); // 이미 처리 완료된 노드 + + // 사이클 탐지 함수 + const dfs = (course) => { + if (visited.has(course)) return false; // 사이클 발견 + if (completed.has(course)) return true; // 이미 확인된 경우 + + visited.add(course); // 현재 노드 방문 중 + for (const nextCourse of graph.get(course)) { + if (!dfs(nextCourse)) return false; // 다음 코스에서 사이클 발견 + } + visited.delete(course); // 탐색 완료 후 제거 + completed.add(course); // 완료된 노드로 기록 + + return true; + }; + + // 각 강좌에 대해 DFS 실행 + for (let i = 0; i < numCourses; i++) { + if (!dfs(i)) return false; // 사이클이 존재하면 false 반환 + } + + return true; // 모든 강좌를 완료할 수 있음 +}; diff --git a/oris8/208_implement-trie-prefix-tree.js b/oris8/208_implement-trie-prefix-tree.js new file mode 100644 index 0000000..69dbf2f --- /dev/null +++ b/oris8/208_implement-trie-prefix-tree.js @@ -0,0 +1,85 @@ +/** + * 208. Implement Trie (Prefix Tree) +Medium +Topics +Companies +A trie (pronounced as "try") or prefix tree is a tree data structure used to efficiently store and retrieve keys in a dataset of strings. There are various applications of this data structure, such as autocomplete and spellchecker. + +Implement the Trie class: + +Trie() Initializes the trie object. +void insert(String word) Inserts the string word into the trie. +boolean search(String word) Returns true if the string word is in the trie (i.e., was inserted before), and false otherwise. +boolean startsWith(String prefix) Returns true if there is a previously inserted string word that has the prefix prefix, and false otherwise. + +1 <= word.length, prefix.length <= 2000 +word and prefix consist only of lowercase English letters. +At most 3 * 104 calls in total will be made to insert, search, and startsWith. + */ + +// var Trie = function() { +// node +// }; + +class TrieNode { + constructor() { + this.children = {}; + this.words = new Set(); + } +} + +class Trie { + constructor() { + this.root = new TrieNode(); + } + + traverse(word) { + let node = this.root; + for (let char of word) { + node = node.children[char]; + if (!node) return null; + } + return node; + } +} + +/** + * @param {string} word + * @return {void} + */ +Trie.prototype.insert = function (word) { + let node = this.root; + for (const char of word) { + if (!node.children[char]) { + node.children[char] = new TrieNode(); + } + node = node.children[char]; + } + node.words.add(word); +}; + +/** + * @param {string} word + * @return {boolean} + */ +Trie.prototype.search = function (word) { + let node = this.traverse(word); + return !!node && node.words.has(word); +}; + +/** + * @param {string} prefix + * @return {boolean} + */ +Trie.prototype.startsWith = function (prefix) { + let node = this.traverse(prefix); + return !!node; +}; + +/** + * Your Trie object will be instantiated and called as such: + * var obj = new Trie() + * obj.insert(word) + * var param_2 = obj.search(word) + * var param_3 = obj.startsWith(prefix) + */ diff --git a/oris8/213_house-robber-ii.js b/oris8/213_house-robber-ii.js new file mode 100644 index 0000000..ccc35ab --- /dev/null +++ b/oris8/213_house-robber-ii.js @@ -0,0 +1,19 @@ +/** + * 213 / House Robber II / Medium / 13m 27s +/** + * @param {number[]} nums + * @return {number} + */ +var rob = function (nums) { + // T(n) = Math.max(T(n-1), T(n-2) + n) + if (nums.length <= 2) return Math.max(nums[0], nums?.[1] || 0); + + const results = [nums[0], Math.max(nums[0], nums[1])]; + const not1results = [0, nums[1]]; + for (let i = 2; i < nums.length; i++) { + results[i] = Math.max(results[i - 1], results[i - 2] + nums[i]); + not1results[i] = Math.max(not1results[i - 1], not1results[i - 2] + nums[i]); + } + + return Math.max(results[nums.length - 2], not1results[nums.length - 1]); +}; diff --git a/oris8/226_invert-binary-tree.js b/oris8/226_invert-binary-tree.js new file mode 100644 index 0000000..dc122b1 --- /dev/null +++ b/oris8/226_invert-binary-tree.js @@ -0,0 +1,21 @@ +/** + * 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) + * } + */ +/** + * @param {TreeNode} root + * @return {TreeNode} + */ +var invertTree = function (root) { + if (root) { + [root.right, root.left] = [invertTree(root.left), invertTree(root.right)]; + } + // if (!root) return null; + // [root.left, root.right] = [invertTree(root.right), invertTree(root.left)]; + + return root; +}; diff --git a/oris8/371_sum-of-two-integers.js b/oris8/371_sum-of-two-integers.js new file mode 100644 index 0000000..6c24788 --- /dev/null +++ b/oris8/371_sum-of-two-integers.js @@ -0,0 +1,27 @@ +/** + * 371. Sum of Two Integers + * Medium + * + * Given two integers a and b, return the sum of the two integers without using the operators + and -. + * + * -1000 <= a, b <= 1000 + * + * @param {number} a + * @param {number} b + * @return {number} + */ +var getSum = function (a, b) { + // 비트 연산 사용 + /** + * + * XOR :각 비트를 비교하여, 두 비트가 서로 다르면 1을 반환하고, 같으면 0을 반환 + * === carry(올림)를 무시한 덧셈과 동일한 결과 + * + * AND :두 비트가 모두 1인 경우 + * + * 자리올림은 두 비트가 모두 1일때 발생하므로 AND 연산을 통해서 이를 확인하고, 두 비트가 모두 1일 경우 자리올림 수행 (<<) + * + */ + + return b === 0 ? a : getSum(a ^ b, (a & b) << 1); +}; diff --git a/oris8/543_diameter-of-binary-tree.js b/oris8/543_diameter-of-binary-tree.js new file mode 100644 index 0000000..74e03c9 --- /dev/null +++ b/oris8/543_diameter-of-binary-tree.js @@ -0,0 +1,44 @@ +/** + * + * 543. Diameter of Binary Tree +Easy +Topics +Companies +Given the root of a binary tree, return the length of the diameter of the tree. + +The diameter of a binary tree is the length of the longest path between any two nodes in a tree. This path may or may not pass through the root. + +The length of a path between two nodes is represented by the number of edges between them. + +The number of nodes in the tree is in the range [1, 104]. +-100 <= Node.val <= 100 + + * 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) + * } + */ +/** + * @param {TreeNode} root + * @return {number} + */ +var diameterOfBinaryTree = function (root) { + let maxDiameter = 0; + const getBinaryTreeHeight = (node) => { + if (!node) return 0; + + // 현재 노드부터 높이를 재귀적으로 계산 + const right = getBinaryTreeHeight(node.right); + const left = getBinaryTreeHeight(node.left); + + maxDiameter = Math.max(maxDiameter, right + left); + + // 현재 노드를 포함하기 위해 + 1 + return Math.max(right, left) + 1; + }; + + getBinaryTreeHeight(root); + return maxDiameter; +}; diff --git a/oris8/572_subtree-of-another-tree.js b/oris8/572_subtree-of-another-tree.js new file mode 100644 index 0000000..17ca2b7 --- /dev/null +++ b/oris8/572_subtree-of-another-tree.js @@ -0,0 +1,30 @@ +/** + * + * 572 / Subtree of Another Tree / Easy / 23m 12s + * + * 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) + * } + */ +/** + * @param {TreeNode} root + * @param {TreeNode} subRoot + * @return {boolean} + */ +var isSubtree = function (root, subRoot) { + if (!root) return false; + + if (isSameTree(root, subRoot)) return true; + + return isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot); +}; + +var isSameTree = function (t1, t2) { + if (!t1 && !t2) return true; + if (!t1 || !t2 || t1.val !== t2.val) return false; + + return isSameTree(t1.left, t2.left) && isSameTree(t1.right, t2.right); +};