From 45d0647b08e3b4dd5a1b8445a683b59321fad12c Mon Sep 17 00:00:00 2001 From: whewchews Date: Sat, 7 Sep 2024 00:17:46 +0900 Subject: [PATCH 1/5] 1. valid palindrome --- valid-palindrome/whewchews.ts | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 valid-palindrome/whewchews.ts diff --git a/valid-palindrome/whewchews.ts b/valid-palindrome/whewchews.ts new file mode 100644 index 000000000..2f072d1ed --- /dev/null +++ b/valid-palindrome/whewchews.ts @@ -0,0 +1,34 @@ +/* + * 조건 + * 모든 대문자를 소문자로 바꿔서 처리 + * 영어 대소문자, 숫자가 아닌 문자는 제거 후 체크 + * + * 아이디어 + * 정규식으로 문자열 중에 숫자, 문자만 추출 + * 짝수인 경우 123456 + * 1-6, 2-5, 3-4를 비교: length/2번 비교 + * 홀수인 경우 1234567 + * 1-7, 2-6, 3-5를 비교: length/2번 비교 + */ + +function isPalindrome(s: string): boolean { + // TC: O(n) + // SC: O(n) + const str = s + .replace(/[^a-zA-Z0-9]/g, "") + .replace(/\s+/g, "") + .toLocaleLowerCase(); + const len = str.length; + + // TC: O(n) + for (let i = 0; i <= str.length / 2 - 1; i++) { + if (str[i] !== str[len - i - 1]) { + return false; + } + } + + return true; +} + +// TC: O(n) +// SC: O(n) From 88dcf6bcb6832a128b78325d48ab525d34a5d587 Mon Sep 17 00:00:00 2001 From: whewchews Date: Sat, 7 Sep 2024 00:20:36 +0900 Subject: [PATCH 2/5] 2. missing number --- missing-number/whewchews.ts | 39 +++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 missing-number/whewchews.ts diff --git a/missing-number/whewchews.ts b/missing-number/whewchews.ts new file mode 100644 index 000000000..78c4b7cf1 --- /dev/null +++ b/missing-number/whewchews.ts @@ -0,0 +1,39 @@ +/* +* 조건 +* [0, n] 중에 없는 값을 리턴, n == nums.length +* 모든 값은 unique + +* 아이디어 +* => nums.length는 실제 배열 index보다 1이 더 크기 때문에 항상 없는 값이 1개 존재함 +* 0부터 n까지의 모든 값을 set에 저장해둔다. +* set 자료구조를 사용하는 이유는 +* 1. nums에 들어오는 값이 중복값이 존재하지 않기 때문 +* 2. 같은 동작을 배열에서 하게 되면 +* 각 인덱스를 1로 두고 값이 있을때마다 0으로 변경, 1이 있는 index를 찾음으로 풀 수 있음 +* => 이 경우, 남은 값을 찾을 때 배열을 한번 다 돌아야 해서 시간복잡도가 O(n) 더 소요됨. +* nums 배열을 돌며 값이 있을때 마다 set에서 값을 삭제한다. +* set에서 남은 값을 찾아 리턴해준다. +* +*/ +function missingNumber(nums: number[]): number { + // TC: O(n) + // SC: O(n) + const numSet: Set = new Set( + Array(nums.length + 1) + .fill(0) + .map((v, i) => i) + ); + + // TC: O(n) + nums.forEach((n) => { + numSet.delete(n); + }); + + // TC: O(1) + // SC: O(1) + const [lastNum] = numSet.values(); + return lastNum; +} + +// TC: O(n) +// SC: O(n) From 3b1229b5b68326d503343021c958ace6e6d78b10 Mon Sep 17 00:00:00 2001 From: whewchews Date: Sat, 7 Sep 2024 00:25:01 +0900 Subject: [PATCH 3/5] 3. Longest Consecutive Sequence --- longest-consecutive-sequence/whewchews.ts | 61 +++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 longest-consecutive-sequence/whewchews.ts diff --git a/longest-consecutive-sequence/whewchews.ts b/longest-consecutive-sequence/whewchews.ts new file mode 100644 index 000000000..143e543d7 --- /dev/null +++ b/longest-consecutive-sequence/whewchews.ts @@ -0,0 +1,61 @@ +/* +* 조건 +* 연속된 수가 가장 긴 경우, 몇 번인지 구하기. 같은 값은 이어서 연결할 수 있음. +* 시간복잡도는 O(n)이어야함 = nums 배열을 한번만 돌아서 구할 것, 정렬 메소드는 쓸 수 없음(O(nlogn)) +* +* 아이디어 +* 시작지점과 끝나는 지점, 그 길이가 가장 긴 것을 구해야함 +* 배열 값들을 한번만 체크할 수 있도록 배열을 돌면서 값을 set 자료구조에 저장해둔다 +* 이때 set 사용하는 이유는, +* 특정 값이 중복인 경우를 고려할 필요가 없기 때문 +* +* 다시 nums 배열을 돌면서 현재 값 직전값이나 이후값이 있는지, 앞뒤로 연속되는 수가 몇개가 있는지 체크한다 +* 앞뒤로 연속되는 숫자의 개수로 새로운 배열을 만든다 +* 새로 만들어진 배열 중 가장 큰 값을 리턴한다 + +* 이렇게 했을때 leetcode 시간초과가 뜬다. +* 중복계산 하는 부분을 줄여보자. +* 왼쪽에 있는 값은 왼쪽값에서 체크를 할거라 미리 계산해줄 필요가 없다, 현재 값부터 오른쪽 값만 계산한다. +* nums 배열을 돌면서 왼쪽값이 없는 경우만 오른쪽 값에 대해 길이를 계산한다 +* 값에 대한 오른쪽 길이를 이미 계산한 적 있는 경우, memo된 값을 사용한다 +* +*/ +function longestConsecutive(nums: number[]): number { + // TC: O(n) + // SC: O(n) + const numSet: Set = new Set(nums); + + // SC: O(n) + const numLengthMemo: Map = new Map(); + let maxLength = 0; + + // TC: O(n) + for (let n of nums) { + if (!numSet.has(n - 1)) { + let length = 1; + + if (numLengthMemo.has(n)) { + length = numLengthMemo.get(n); + maxLength = Math.max(maxLength, length); + continue; + } + + // TC: O(n) + while (numSet.has(n + length)) { + length++; + } + + numLengthMemo.set(n, length); + maxLength = Math.max(maxLength, length); + } + } + + return maxLength; +} + +function getNumCount(current: number, dict: Map) { + return dict.get(current) ?? 0; +} + +// TC: O(n) +// SC: O(n) From d0efeefe6c22e6141916495e7e6f94e610975d05 Mon Sep 17 00:00:00 2001 From: whewchews Date: Sat, 7 Sep 2024 00:48:45 +0900 Subject: [PATCH 4/5] 4. word search --- word-search/whewchews.ts | 64 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 word-search/whewchews.ts diff --git a/word-search/whewchews.ts b/word-search/whewchews.ts new file mode 100644 index 000000000..bfe77e29c --- /dev/null +++ b/word-search/whewchews.ts @@ -0,0 +1,64 @@ +/* +* 조건 +* 같은 단어 위치는 한번만 쓰인다 +* 이웃해서 연속된 단어가 있는지 찾는다 + +* 백트래킹 +* 모든 원소를 완전탐색하기 위한 목적으로 사용. +* 단순히 완전탐색하는 것이 아니라 조건에 따라서 유망한 노드로 이동. +*/ +function exist(board: string[][], word: string): boolean { + const m = board.length; + const n = board[0].length; + const l = word.length; + const directions = [ + [-1, 0], // 상 + [1, 0], // 하 + [0, -1], // 좌 + [0, 1], // 우 + ]; + + const backtrack = ( + col: number, + row: number, + idx: number, + visited: Set + ): boolean => { + if (idx === l) { + return true; + } + if ( + col < 0 || + col >= m || + row < 0 || + row >= n || + board[col][row] !== word[idx] || + visited.has(`${col},${row}`) + ) { + return false; + } + + visited.add(`${col},${row}`); + + for (const [dCol, dRow] of directions) { + if (backtrack(col + dCol, row + dRow, idx + 1, visited)) { + return true; + } + } + + visited.delete(`${col},${row}`); + return false; + }; + + for (let col = 0; col < m; col++) { + for (let row = 0; row < n; row++) { + if (backtrack(col, row, 0, new Set())) { + return true; + } + } + } + return false; +} + +// TC: O(m*n*4^l) <= m*n: 보드의 크기, l: 단어의 길이. 최대 4개 방향으로 이동 가능 +// SC: O(l) <= 단어 길이만큼 방문 가능 From 2286ca987af79e8a5c23e3471afe6394612b4496 Mon Sep 17 00:00:00 2001 From: whewchews Date: Sat, 7 Sep 2024 00:57:09 +0900 Subject: [PATCH 5/5] 5. Maximum Product Subarray --- maximum-product-subarray/whewchews.ts | 35 +++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 maximum-product-subarray/whewchews.ts diff --git a/maximum-product-subarray/whewchews.ts b/maximum-product-subarray/whewchews.ts new file mode 100644 index 000000000..27cb59be0 --- /dev/null +++ b/maximum-product-subarray/whewchews.ts @@ -0,0 +1,35 @@ +/* +* 조건 +* 가장 큰 배열 곱을 찾아서 return +* 32-bit integer +* -10<=num[i]<=10 + +* 아이디어 +* 이전 최대값, 최소값을 구해둔다 +* 최대곱이 나올 수 있는 경우 +* 1) 최소값 곱한것(-*-) +* 2) 최대값 곱한것(+*+) +* 3) 자기자신인 경우(+) +* 배열을 돌면서 세 가지 중 최대최소값을 갱신해나간다 +* +*/ +function maxProduct(nums: number[]): number { + let max = nums[0]; + let min = nums[0]; + let result = nums[0]; + + for (let i = 1; i < nums.length; i++) { + const candidates = [nums[i] * max, nums[i], nums[i] * min]; + let currMax = Math.max(...candidates); + let currMin = Math.min(...candidates); + + max = currMax; + min = currMin; + + result = Math.max(currMax, result); + } + return result; +} + +// TC: O(n) +// SC: O(1)