Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[강희찬] WEEK 15 Solution #605

Merged
merged 5 commits into from
Nov 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions alien-dictionary/HC-kang.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/**
* https://leetcode.com/problems/alien-dictionary
* T.C. O(N * M) N: number of words, M: average length of word
* S.C. O(1) 26 characters
*/
function alienOrder(words: string[]): string {
const graph: Record<string, Set<string>> = {};
const inDegree: Record<string, number> = {};

// Initialize the graph
for (const word of words) {
for (const char of word) {
if (!graph[char]) {
graph[char] = new Set();
inDegree[char] = 0;
}
}
}

// Build the graph
for (let i = 0; i < words.length - 1; i++) {
const word1 = words[i];
const word2 = words[i + 1];

// Check invalid case: if word1 is longer and is prefix of word2
if (word1.length > word2.length && word1.startsWith(word2)) {
return '';
}

let j = 0;
while (j < Math.min(word1.length, word2.length)) {
if (word1[j] !== word2[j]) {
const curSet = graph[word1[j]];
if (!curSet.has(word2[j])) {
curSet.add(word2[j]);
inDegree[word2[j]]++;
}
break;
}
j++;
}
}

// Topological sort
const queue: string[] = [];
for (const [char, degree] of Object.entries(inDegree)) {
if (degree === 0) {
queue.push(char);
}
}

const result: string[] = [];
while (queue.length) {
const char = queue.shift();
result.push(char!);
for (const next of graph[char!]) {
inDegree[next]--;
if (inDegree[next] === 0) {
queue.push(next);
}
}
}

return result.length === Object.keys(inDegree).length //
? result.join('')
: '';
}
32 changes: 32 additions & 0 deletions longest-palindromic-substring/HC-kang.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* https://leetcode.com/problems/longest-palindromic-substring
* T.C. O(n^2)
* S.C. O(1)
*/
function longestPalindrome(s: string): string {
if (s.length < 2) return s;
let start = 0;
let end = 0;

for (let i = 0; i < s.length; i++) {
const len1 = expandBothSides(s, i, i); // odd
const len2 = expandBothSides(s, i, i + 1); // even
Comment on lines +12 to +13
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

별거 아닙니다만, 평소 알고리즘 푸는 습관이 그대로 코드에 드러난다고 생각하기 때문에 변수 명을 odd, even과 관련된 걸로 했으면 주석이 없어도 괜찮지 않았을까 싶습니다 :)

const len = Math.max(len1, len2);

if (len > end - start) {
start = i - Math.floor((len - 1) / 2);
end = i + Math.floor(len / 2);
}
}

return s.slice(start, end + 1);
}

function expandBothSides(s: string, left: number, right: number): number {
while (0 <= left && right < s.length && s[left] === s[right]) {
left--;
right++;
}

return right - left - 1;
}
22 changes: 22 additions & 0 deletions rotate-image/HC-kang.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* https://leetcode.com/problems/rotate-image
* T.C. O(n^2)
* S.C. O(1)
*/
function rotate(matrix: number[][]): void {
const n = matrix.length;

// transpose
for (let i = 0; i < n; i++) {
for (let j = i; j < n; j++) {
[matrix[i][j], matrix[j][i]] = [matrix[j][i], matrix[i][j]];
}
}

// reverse
for (let i = 0; i < n; i++) {
for (let j = 0; j < n / 2; j++) {
[matrix[i][j], matrix[i][n - j - 1]] = [matrix[i][n - j - 1], matrix[i][j]];
}
}
}
28 changes: 28 additions & 0 deletions subtree-of-another-tree/HC-kang.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// class TreeNode {
// val: number;
// left: TreeNode | null;
// right: TreeNode | null;
// constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
// this.val = val === undefined ? 0 : val;
// this.left = left === undefined ? null : left;
// this.right = right === undefined ? null : right;
// }
// }

/**
* https://leetcode.com/problems/subtree-of-another-tree
* T.C. O(n * m)
* S.C. O(n)
*/
function isSubtree(root: TreeNode | null, subRoot: TreeNode | null): boolean {
if (!root) return false;
if (isSameTree(root, subRoot)) return true;
return isSubtree(root.left, subRoot) || isSubtree(root.right, subRoot);
}

function isSameTree(p: TreeNode | null, q: TreeNode | null): boolean {
if (!p && !q) return true;
if (!p || !q) return false;
Comment on lines +24 to +25
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이거 혹시 한줄로
if(!p || !q) reutrn !p && !q;
로 바꿀 수 있지 않을까요?
한줄 한줄의 의미를 살리고 가독성 면에서는 명확하게 전달하는 측면에서는 현재 풀이가 좋다고 생각합니다!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

early return인데 24, 25줄이 서로 겹치는 부분이 있어서 조금 애매한 것 같습니다.

if !p && !q
else if (p && q) && (p.val == q.val)
else

이렇게 나누면 겹치는 조건 없이 else문에서 (!p && q) || (p && !q) || (p.val != q.val) 조건을 처리하기 좋을 것 같습니다

if (p.val !== q.val) return false;
return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
}
26 changes: 26 additions & 0 deletions validate-binary-search-tree/HC-kang.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// class TreeNode {
// val: number;
// left: TreeNode | null;
// right: TreeNode | null;
// constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
// this.val = val === undefined ? 0 : val;
// this.left = left === undefined ? null : left;
// this.right = right === undefined ? null : right;
// }
// }

/**
* https://leetcode.com/problems/validate-binary-search-tree
* T.C. O(n)
* S.C. O(n)
*/
function isValidBST(root: TreeNode | null): boolean {
return validate(root, null, null);
}

function validate(node: TreeNode | null, min: number | null, max: number | null): boolean {
if (!node) return true;
if (min !== null && node.val <= min) return false;
if (max !== null && node.val >= max) return false;
return validate(node.left, min, node.val) && validate(node.right, node.val, max);
}