diff --git a/3sum/seongmin36.js b/3sum/seongmin36.js new file mode 100644 index 0000000000..d9f6378077 --- /dev/null +++ b/3sum/seongmin36.js @@ -0,0 +1,41 @@ +/** +중요한 것은 짝을 찾는 것이다. +즉, 정수가 0이 되는 '역원(inverse)'을 찾아야 한다. +역원을 담을 저장소가 필요한데, +찾아야할 역원은 여러개일 필요가 없기 때문에 주머니 역할로 Set 인스턴스를 사용한다. +중복 조건은 정렬된 배열에서 현재 인덱스보다 큰 원소 중에서 동일한 값을 제외한다. + */ +/** + * @param {number[]} nums + * @return {number[][]} + */ + +function threeSum(nums) { + let result = []; + + nums.sort((a, b) => a - b); + + for (let i = 0; i < nums.length; i++) { + if (nums[i] > 0) break; + + // 중복 제거 → i>0 이웃한 두 수가 일치하면 skip + if (i > 0 && nums[i] === nums[i - 1]) continue; + + let pocket = new Set(); + + for (let g = i + 1; g < nums.length; g++) { + let find_num = -(nums[i] + nums[g]); + + if (pocket.has(find_num)) { + result.push([nums[i], find_num, nums[g]]); + + // 중복 제거 → 정렬된 상태에서 같은 수가 나오면 shift + while (g + 1 < nums.length && nums[g] === nums[g + 1]) { + g++; + } + } + pocket.add(nums[g]); + } + } + return result; +} diff --git a/climbing-stairs/seongmin36.js b/climbing-stairs/seongmin36.js new file mode 100644 index 0000000000..f103769dec --- /dev/null +++ b/climbing-stairs/seongmin36.js @@ -0,0 +1,18 @@ +/** + * @param {number} n + * @return {number} + */ +function climbStairs(n) { + if (n <= 2) return n; + + let arr = new Array(n + 1); + + arr[0] = 1; + arr[1] = 2; + + for (let i = 2; i < arr.length; i++) { + arr[i] = arr[i - 2] + arr[i - 1]; + } + + return arr[n - 1]; +} diff --git a/product-of-array-except-self/seongmin36.js b/product-of-array-except-self/seongmin36.js new file mode 100644 index 0000000000..0f14d69033 --- /dev/null +++ b/product-of-array-except-self/seongmin36.js @@ -0,0 +1,34 @@ +/** +문제의 핵심은 '어떻게 인덱스와 곱을 이중 반복문을 쓰지 않고 해결하느냐'다. 'Goal' → 시간 복잡도 : O(N) +여기서 사용된 개념: 'Two Pointer' +Two Pointer? → '배열에서 순차적으로 접근해야 할 때 두 개의 점의 위치를 기록하면서 처리하는 알고리즘' +이중 반복을 사용하지 않고, 각 인덱스를 순회하면서 answer[index]에 본인을 제외한 곱셈을 중첩시킨다. +본인을 제외한 나머지 원소의 곱이기 때문에 left와 right로 나눠서 중첩된 곱셈을 다시 곱한다. + */ + +/** + * @param {number[]} nums + * @return {number[]} + */ +function productExceptSelf(nums) { + let answer = new Array(nums.length).fill(1); + + let left = 0; + let right = nums.length - 1; + + let mul_left = 1; + let mul_right = 1; + + while (left < nums.length && right >= 0) { + answer[left] *= mul_left; + mul_left *= nums[left]; // 자기 자신 제외 곱 + + answer[right] *= mul_right; + mul_right *= nums[right]; + + left++; + right--; + } + + return answer; +} diff --git a/valid-anagram/seongmin36.js b/valid-anagram/seongmin36.js new file mode 100644 index 0000000000..df5a413865 --- /dev/null +++ b/valid-anagram/seongmin36.js @@ -0,0 +1,31 @@ +/** +결국 같아야 것은 string의 길이와 안에 들어간 각 character의 갯수다. +즉, s와 t의 문자의 갯수와 같으면 된다. +map을 사용하여 key와 value자리에 각각 문자, 갯수를 받는다. +s와 t를 비교하며 해당하는 문자 갯수-1을 한다. +각 key의 value를 문제없이 차감했다면 true를 반환. 그 외 false를 반환 + */ + +/** + * @param {string} s + * @param {string} t + * @return {boolean} + */ +function isAnagram(s, t) { + if (s.length !== t.length) return false; + + let map_s = new Map(); + + for (let char of s) { + map_s.set(char, (map_s.get(char) || 0) + 1); + } + + for (let char of t) { + if (!map_s.has(char) || map_s.get(char) === 0) { + return false; + } + map_s.set(char, map_s.get(char) - 1); + } + + return true; +} diff --git a/validate-binary-search-tree/seongmin36.js b/validate-binary-search-tree/seongmin36.js new file mode 100644 index 0000000000..13af6f918a --- /dev/null +++ b/validate-binary-search-tree/seongmin36.js @@ -0,0 +1,32 @@ +/** +이진 탐색 트리의 특징은 다음과 같다. +- 부모 노드를 기준으로 left는 부모보다 작은 수 +- 부모 노드를 기준으로 right는 부모보다 큰 수 +이 문제에서 구하려는 것은 '주어진 트리가 이진 탐색 트리를 만족하는가?'이다 +이는 재귀함수를 사용하여 깊이 우선 탐색(DFS)을 통해 해결할 수 있다. +여기서 validate는 'BST'의 특징을 비교하는 함수인데, +validate()는 validate를 반환하면서 깊이 탐색하여 최종 참/거짓을 판별한다. + */ +/** + * 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 {boolean} + */ +function isValidBST(root) { + function validate(p, min, max) { + if (p === null) return true; + + if (p.val <= min || p.val >= max) return false; + + return validate(p.left, min, p.val) && validate(p.right, p.val, max); + } + + return validate(root, -Infinity, Infinity); +}