diff --git a/clone-graph/Jeehay28.ts b/clone-graph/Jeehay28.ts new file mode 100644 index 000000000..166916026 --- /dev/null +++ b/clone-graph/Jeehay28.ts @@ -0,0 +1,67 @@ +class _Node { + val: number; + neighbors: _Node[]; + + constructor(val?: number, neighbors?: _Node[]) { + this.val = val === undefined ? 0 : val; + this.neighbors = neighbors === undefined ? [] : neighbors; + } +} + +// TC: O(V + E), where V is the number of vertices and E is the number of edges +// SC: O(V + E) +function cloneGraph(node: _Node | null): _Node | null { + // 1: [2, 4] + // 2: [1, 3] + // 3: [2, 4] + // 4: [1, 3] + + const clones = new Map<_Node, _Node>(); + // original Node: cloned Node + + if (!node) return null; + + const dfs = (node: _Node) => { + if (clones.has(node)) { + return clones.get(node); + } + + const clone = new _Node(node.val); + clones.set(node, clone); + + for (const nei of node.neighbors) { + clone.neighbors.push(dfs(nei)!); + } + + return clone; + }; + + return dfs(node)!; +} + + +// TC: O(V + E) +// SC: O(V + E) +// function cloneGraph(node: _Node | null): _Node | null { +// if (!node) return null; + +// const clone: _Node = new _Node(node.val); +// const clones = new Map<_Node, _Node>(); +// clones.set(node, clone); +// const queue: _Node[] = [node]; // BFS -> use queue + +// while (queue.length > 0) { +// const node = queue.shift()!; +// for (const nei of node.neighbors) { +// if (!clones.has(nei)) { +// clones.set(nei, new _Node(nei.val)); +// queue.push(nei); +// } +// clones.get(node)!.neighbors.push(clones.get(nei)!); +// } +// } + +// return clone; +// } + + diff --git a/longest-repeating-character-replacement/Jeehay28.ts b/longest-repeating-character-replacement/Jeehay28.ts new file mode 100644 index 000000000..13c81ac6f --- /dev/null +++ b/longest-repeating-character-replacement/Jeehay28.ts @@ -0,0 +1,27 @@ +// TC: O(n) +// SC: O(1) +function characterReplacement(s: string, k: number): number { + const freqMap = new Map(); + let left = 0; + let maxFreqCnt = 0; + let result = 0; + + for (let right = 0; right < s.length; right++) { + const ch = s[right]; + freqMap.set(ch, (freqMap.get(ch)! | 0) + 1); + maxFreqCnt = Math.max(maxFreqCnt, freqMap.get(ch)!); + + while (right - left + 1 - maxFreqCnt > k) { + // Shrink the sliding window by moving the left pointer to the right. + // As we move left, decrease the frequency count of the character being excluded from the window. + const ch = s[left]; + freqMap.set(ch, freqMap.get(ch)! - 1); + left++; + } + + result = Math.max(result, right - left + 1); + } + + return result; +} + diff --git a/palindromic-substrings/Jeehay28.ts b/palindromic-substrings/Jeehay28.ts new file mode 100644 index 000000000..935e6139f --- /dev/null +++ b/palindromic-substrings/Jeehay28.ts @@ -0,0 +1,97 @@ +// TC: O(n^2) +// SC: O(1) +function countSubstrings(s: string): number { + // Treat each index as the center of potential palindromic substrings + let cnt = 0; + + for (let i = 0; i < s.length; i++) { + let start = i; + let end = i; + + // Check for odd-length palindromes centered at i + while (start >= 0 && end < s.length && s[start] === s[end]) { + cnt++; + start--; // <---- + end++; // -----> + } + + // Check for even-length palindromes centered between i and i + 1 + start = i; + end = i + 1; + + while (start >= 0 && end < s.length && s[start] === s[end]) { + cnt++; + start--; + end++; + } + } + + return cnt; +} + +// TC: O(n^2) +// SC: O(n^2) +/* +function countSubstrings(s: string): number { + // dp[(start, end)] = s[start] === s[end] && dp[(start + 1, end - 1)] + + // A new starting character + an existing palindromic substring + a new ending character + // start dp[(start + 1, end - 1)] end + + const dp = new Map(); + + for (let end = 0; end < s.length; end++) { + // start ranges from end down to 0 + for (let start = end; start >= 0; start--) { + const key = `${start}-${end}`; + if (start === end) { + // "a" + dp.set(key, true); + } else if (start + 1 === end) { + // "aa" + dp.set(key, s[start] === s[end]); + } else { + const prevKey = `${start + 1}-${end - 1}`; + dp.set(key, s[start] === s[end] && dp.get(prevKey) === true); + } + } + } + + let cnt = 0; + + for (const [key, value] of dp.entries()) { + if (value) { + cnt++; + } + } + + return cnt; +} +*/ + +// TC: O(n^3) +// SC: O(1) +// function countSubstrings(s: string): number { +// const isPalindromic = (left: number, right: number) => { +// while (left < right) { +// if (s[left] !== s[right]) return false; + +// left++; +// right--; +// } + +// return true; +// }; + +// let cnt = 0; + +// for (let i = 0; i < s.length; i++) { +// for (let j = i; j < s.length; j++) { +// if (isPalindromic(i, j)) { +// cnt++; +// } +// } +// } + +// return cnt; +// } diff --git a/reverse-bits/Jeehay28.ts b/reverse-bits/Jeehay28.ts new file mode 100644 index 000000000..970637212 --- /dev/null +++ b/reverse-bits/Jeehay28.ts @@ -0,0 +1,70 @@ +// TC: O(1) +// SC: O(1) +function reverseBits(n: number): number { + let stack: number[] = []; + + while (stack.length < 32) { + stack.push(n % 2); + n = Math.floor(n / 2); + } + + let output: number = 0; + let scale: number = 1; + + while (stack.length > 0) { + output += stack.pop()! * scale; + scale *= 2; + } + + return output; +} + +// TC: O(1) +// SC: O(1) +/* +function reverseBits(n: number): number { + let result = 0; + + for (let i = 0; i < 32; i++) { + let bit = n & 1; + result = (result << 1) | bit; + n = n >>> 1; + } + + return result >>> 0; +} +*/ + +/* +n & 1 +- get last bit +- equivalent to n % 2 for non-negative integer + +n << 1 +- left shift (multiply by 2) + +n >>> 1 +- Unsigned right shift (divide by 2) +- ignores sign + +n >>> 0 +- no shift, just cast to unsigned + +const signed = -1; // Binary: 11111111111111111111111111111111 +const unsigned = signed >>> 0; // 4294967295 + +JavaScript/TypeScript only has one number type — a 64-bit float. itwise operations use 32-bit signed integers. + To return a 32-bit unsigned integer, use >>> 0 on the result. + + 🔧 Bitwise Operations in JavaScript — Summary + 1. Bitwise operations in JavaScript (&, |, ^, ~, <<, >>, >>>) are always performed on 32-bit signed integers. + + 2. Internally: + - JavaScript converts your number into a 32-bit signed integer + - Performs the bitwise operation + - Then converts it back into a regular 64-bit number (JavaScript's only number type) + + 3. If you need the result as a 32-bit unsigned integer (like for LeetCode problems dealing with uint32): + - Use >>> 0 at the end of your result + - This forces the result to be treated as an unsigned 32-bit integer +*/