diff --git a/container-with-most-water/HC-kang.ts b/container-with-most-water/HC-kang.ts new file mode 100644 index 000000000..82666cfa2 --- /dev/null +++ b/container-with-most-water/HC-kang.ts @@ -0,0 +1,21 @@ +/** + * https://leetcode.com/problems/container-with-most-water/ + * T.C. O(n) + * S.C. O(1) + */ +function maxArea(height: number[]): number { + let [res, i, j] = [0, 0, height.length - 1]; + + while (i < j) { + const volume = Math.min(height[i], height[j]) * (j - i); + res = Math.max(res, volume); + + if (height[i] < height[j]) { + i++; + } else { + j--; + } + } + + return res; +} diff --git a/design-add-and-search-words-data-structure/HC-kang.ts b/design-add-and-search-words-data-structure/HC-kang.ts new file mode 100644 index 000000000..efa102152 --- /dev/null +++ b/design-add-and-search-words-data-structure/HC-kang.ts @@ -0,0 +1,102 @@ +/** + * https://leetcode.com/problems/design-add-and-search-words-data-structure + */ +// Using Trie +class WordDictionary { + constructor(private root: Record = {}) {} + + /** + * T.C. O(L) L: length of a word + * S.C. O(L) + */ + addWord(word: string): void { + let node = this.root; + for (const char of word) { + if (!node[char]) { + node[char] = {}; + } + node = node[char]; + } + node['isEnd'] = true; + } + + /** + * T.C. O(N) - there are only 2 dots in the word(26 * 26 * N) + * S.C. O(N * L) N: number of words, L: length of a word + */ + search(word: string): boolean { + return this.dfs(word, this.root); + } + + private dfs(word: string, node: Record): boolean { + for (let i = 0; i < word.length; i++) { + if (word[i] === '.') { + for (const key in node) { + if (this.dfs(word.slice(i + 1), node[key])) { + return true; + } + } + return false; + } + if (!node[word[i]]) { + return false; + } + node = node[word[i]]; + } + return !!node['isEnd']; + } +} + +// Using Array and Set +class WordDictionary { + constructor( + private words: Set[] = Array.from({ length: 25 }, () => new Set()) + ) {} + + /** + * T.C. O(1) + * S.C. O(N * L) + */ + addWord(word: string): void { + this.words[word.length - 1].add(word); + } + + /** + * T.C. O(N * L) N: number of words, L: length of a word + * S.C. O(1) + */ + search(word: string): boolean { + const hasDot = word.indexOf('.') !== -1; + const set = this.words[word.length - 1]; + + if (!hasDot) { + return set.has(word); + } + + for (const w of set) { + let i = 0; + while (i < word.length) { + if (word[i] == '.') { + i++; + continue; + } + if (word[i] !== w[i]) { + break; + } + i++; + } + + if (i === word.length) { + return true; + } + } + return false; + } +} + +/** + * Your WordDictionary object will be instantiated and called as such: + * var obj = new WordDictionary() + * obj.addWord(word) + * var param_2 = obj.search(word) + */ diff --git a/longest-increasing-subsequence/HC-kang.ts b/longest-increasing-subsequence/HC-kang.ts new file mode 100644 index 000000000..0d4e5e284 --- /dev/null +++ b/longest-increasing-subsequence/HC-kang.ts @@ -0,0 +1,32 @@ +/** + * https://leetcode.com/problems/longest-increasing-subsequence + * T.C. O(nlogn) + * S.C. O(n) + */ +function lengthOfLIS(nums: number[]): number { + const sub: number[] = []; + + function findSlot(num: number): number { + let left = 0; + let right = sub.length - 1; + + while (left <= right) { + const mid = Math.floor((left + right) / 2); + if (sub[mid] < num) { + left = mid + 1; + } else { + right = mid - 1; + } + } + + return left; + } + + for (let i = 0; i < nums.length; i++) { + const num = nums[i]; + const slot = findSlot(num); + sub[slot] = num; + } + + return sub.length; +} diff --git a/spiral-matrix/HC-kang.ts b/spiral-matrix/HC-kang.ts new file mode 100644 index 000000000..f2d1616e2 --- /dev/null +++ b/spiral-matrix/HC-kang.ts @@ -0,0 +1,44 @@ +/** + * https://leetcode.com/problems/spiral-matrix + * T.C. O(m * n) + * S.C. O(m * n) + */ +function spiralOrder(matrix: number[][]): number[] { + const clockwise = [ + [0, 1], + [1, 0], + [0, -1], + [-1, 0], + ]; + let currentDirection = 0; + + const visited = new Array(matrix.length) + .fill(0) + .map(() => new Array(matrix[0].length).fill(false)); + + const result: number[] = []; + + let row = 0; + let col = 0; + + while (result.length < matrix.length * matrix[0].length) { + result.push(matrix[row][col]); + visited[row][col] = true; + + const nextRow = row + clockwise[currentDirection][0]; + const nextCol = col + clockwise[currentDirection][1]; + + if ( + nextRow < 0 || nextRow >= matrix.length || + nextCol < 0 || nextCol >= matrix[0].length || + visited[nextRow][nextCol] + ) { + currentDirection = (currentDirection + 1) % 4; + } + + row += clockwise[currentDirection][0]; + col += clockwise[currentDirection][1]; + } + + return result; +} diff --git a/valid-parentheses/HC-kang.ts b/valid-parentheses/HC-kang.ts new file mode 100644 index 000000000..57037196b --- /dev/null +++ b/valid-parentheses/HC-kang.ts @@ -0,0 +1,17 @@ +/** + * https://leetcode.com/problems/valid-parentheses + * T.C. O(n) + * S.C. O(n) + */ +function isValid(s: string): boolean { + const pairs: Record = { '{': '}', '[': ']', '(': ')' }; + const stack: string[] = []; + + if (s.length % 2 == 1) return false; + + for (const char of s) { + if (pairs[char]) stack.push(char); + else if (char != pairs[stack.pop()!]) return false; + } + return !stack.length; +}