diff --git a/3sum/jangwonyoon.js b/3sum/jangwonyoon.js new file mode 100644 index 000000000..3ad3dceb6 --- /dev/null +++ b/3sum/jangwonyoon.js @@ -0,0 +1,50 @@ +/** + * @param {number[]} nums + * @return {number[][]} + * + * 1. 투포인터를 사용하기 위해 정렬 + * 2. 투포인터를 사용하여 합이 0인 경우 추가 + * 3. 중복 된 값 스킵 + * + * 시간 복잡도: O(n^2) + * 공간 복잡도: O(K + kLogK) (K: 결과 배열의 크기, kLogK: 정렬 공간) + */ +/** + * @param {number[]} nums + * @return {number[][]} + */ +var threeSum = function(nums) { + const arr = []; + + // 투포인터를 사용하기 위해 정렬 + nums.sort((a, b) => a - b); + + for (let i = 0; i < nums.length - 2; i++) { + // 중복 된 값 스킵 + if (i > 0 && nums[i] === nums[i - 1]) continue; + + let left = i + 1; + let right = nums.length - 1; + + while (left < right) { + const sum = nums[i] + nums[left] + nums[right]; + + if (sum === 0) { + arr.push([nums[i], nums[left], nums[right]]); + + // 중복 된 값 스킵 + while (left < right && nums[left] === nums[left + 1]) left++; + while (left < right && nums[right] === nums[right - 1]) right--; + + left++; + right--; + } else if (sum > 0) { + right--; + } else { + left++; + } + } + } + + return arr; +}; diff --git a/climbing-stairs/jangwonyoon.js b/climbing-stairs/jangwonyoon.js new file mode 100644 index 000000000..65765fa08 --- /dev/null +++ b/climbing-stairs/jangwonyoon.js @@ -0,0 +1,26 @@ +/** + * @param {number} n + * @return {number} + * 점화식: f(n) = f(n-1) + f(n-2) + * 초기값: f(1) = 1, f(2) = 2 + * 시간 복잡도: O(n) + * 공간 복잡도: O(1) + */ + +var climbStairs = function(n) { + // 초기값 처리 + if (n === 1) return 1; + if (n === 2) return 2; + + let prev = 1; + let curr = 2; + + // 점화식 계산 + for (let i = 3; i <= n; i++) { + const next = prev + curr; + prev = curr; + curr = next; + } + + return curr; +}; diff --git a/product-of-array-except-self/jangwonyoon.js b/product-of-array-except-self/jangwonyoon.js new file mode 100644 index 000000000..0db6d63a5 --- /dev/null +++ b/product-of-array-except-self/jangwonyoon.js @@ -0,0 +1,31 @@ +/** +* 본인을 기준으로 좌측과, 우측 나눠서 곱한다. +* 담아놓을 변수를 놓고 진행한다. + * @param {number[]} nums + * @return {number[]} + * + * 시간 복잡도: O(n) + * 공간 복잡도: O(n) + */ +var productExceptSelf = function(nums) { + const n = nums.length; + const left = Array(n).fill(1); + const right = Array(n).fill(1); + const res = Array(n); + + // 좌측 곱 + for (let i = 1; i < n; i++) { + left[i] = nums[i - 1] * left[i - 1]; + } + + // 우측 곱 + for (let i = n - 2; i >= 0; i--) { + right[i] = nums[i + 1] * right[i + 1]; + } + + for (let i = 0; i < n; i++) { + res[i] = left[i] * right[i]; + } + + return res; +}; diff --git a/valid-anagram/jangwonyoon.js b/valid-anagram/jangwonyoon.js new file mode 100644 index 000000000..2fe299640 --- /dev/null +++ b/valid-anagram/jangwonyoon.js @@ -0,0 +1,50 @@ +/** + * @param {string} s + * @param {string} t + * @return {boolean} + */ + +/** + * 유니크한 값만 확인한다. + * 1. core: Map 사용하고, 모든 string을 할당한다. + * 2. string을 순회해서 할당한다. + * 3. map에 요소가 있으면 있으면 + 1, 없으면 1 + * 4. map을 순회해서 요소가 있다면 -1을 해준다. + * 5. HashMap을 다시 한번 순회해서, 1이상 값이 있다면 유니크한 값이 아니기 때문에 false, HashMap의 모든 값들이 0이면 true + + * 공간복잡도 O(N) + * 시간복잡도 O(N) + */ + + +var isAnagram = function(s, t) { + const hashMap = new Map(); + + // 예외 처리 + if (s.length !== t.length) { + return false; + } + + + for (const string of s) { + if (!hashMap.has(string)) { + hashMap.set(string, 1) + } else { + hashMap.set(string, hashMap.get(string) + 1) + } + } + + for (const string of t) { + if (hashMap.has(string)) { + hashMap.set(string, hashMap.get(string) - 1); + } + } + + // 0이 아닌 값이 있는경우 - false + for (const [key , value] of hashMap) { + // early return + if (value > 0) return false; + } + + return true; +}; diff --git a/validate-binary-search-tree/jangwonyoon.js b/validate-binary-search-tree/jangwonyoon.js new file mode 100644 index 000000000..542294b16 --- /dev/null +++ b/validate-binary-search-tree/jangwonyoon.js @@ -0,0 +1,42 @@ +/** + * 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} + * + * DFS를 사용하여 왼쪽 노드와 오른쪽 노드를 검증한다. + * + * 시간 복잡도: O(n) + * 공간 복잡도: O(n) + */ +var isValidBST = function(root) { + const MAX_VALUE = Infinity; + const MIN_VALUE = -Infinity; + + const validate = (node, min, max) => { + // 재귀 탈출 조건 + if (!node) return true; + + // 예외 처리 - 현재 노드의 값이 최소값보다 작거나 최대값보다 크면 예외 처리 + if (node.val <= min || node.val >= max) return false; + + const leftNode = node.left; + const rightNode = node.right; + + // 왼쪽 노드 검증 - 현재 값이 제일 크고, 왼쪽은 본인보다 작아야한다. + const validateLeftNode = validate(leftNode, min , node.val); + + // 오른쪽 노드 검증 - 현재 값이 제일 작으며, 우측 노드 값이 본인 보다 커야한다. + const validateRightNode = validate(rightNode, node.val, max) + + return validateLeftNode && validateRightNode; + } + + return validate(root, MIN_VALUE, MAX_VALUE); +};