Skip to content

Commit a4feab1

Browse files
committed
add some prob-sols and update some approach
1 parent 44f90d2 commit a4feab1

12 files changed

+196
-103
lines changed
Lines changed: 28 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,33 @@
11
function deleteNode(root: TreeNode | null, key: number): TreeNode | null {
2-
if (root === null) return root;
3-
if (root.val === key) {
4-
const { left, right } = root;
5-
if (left === null) return right;
6-
else if (right === null) return left;
7-
let ptr = left;
8-
while (ptr.right !== null) ptr = ptr.right;
9-
ptr.right = right;
10-
return left;
11-
} else if (root.left && root.left.val === key) {
12-
const { left, right } = root.left;
13-
if (left === null) root.left = right;
14-
else {
15-
let ptr = left;
16-
while (ptr.right !== null) ptr = ptr.right;
17-
ptr.right = right;
18-
root.left = left;
19-
}
20-
} else if (root.right && root.right.val === key) {
21-
const { left, right } = root.right;
22-
if (left === null) root.right = right;
23-
else {
24-
let ptr = left;
25-
while (ptr.right !== null) ptr = ptr.right;
26-
ptr.right = right;
27-
root.right = left;
28-
}
29-
} else if (root.val < key) {
30-
root.right = deleteNode(root.right, key);
31-
} else {
2+
// case 0. nothing to kill
3+
if (root === null) return null;
4+
5+
// case 1. key in the root.left
6+
if (key < root.val) {
327
root.left = deleteNode(root.left, key);
8+
return root;
9+
}
10+
11+
// case 2. key in the root.right
12+
if (key > root.val) {
13+
root.right = deleteNode(root.right, key);
14+
return root;
3315
}
16+
17+
// case 3. root is the key
18+
const left = root.left,
19+
right = root.right;
20+
21+
if (left === null) return right;
22+
if (right === null) return left;
23+
24+
// so we need to remove the root, and choose a new root val
25+
// from left's right-most (or right's left-most)
26+
let ptr = left;
27+
while (ptr.right !== null) ptr = ptr.right;
28+
29+
root.val = ptr.val;
30+
root.left = deleteNode(left, ptr.val); // since we pick the left's rightmost, recursion kill this picked node
31+
3432
return root;
3533
}
Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,25 @@
11
function increasingBST(root: TreeNode | null): TreeNode | null {
2-
// do in order traversal first
3-
if (root === null) return null;
2+
// let's do morris traversal
3+
let cur = root;
4+
let prevRoot = new TreeNode(0);
5+
let prev = prevRoot;
46

5-
const inorder = (node: TreeNode | null): number[] => {
6-
return node === null ? [] : [...inorder(node.left), node.val, ...inorder(node.right)];
7-
};
7+
while (cur !== null) {
8+
if (cur.left !== null) {
9+
const left = cur.left;
10+
cur.left = null; // prune
811

9-
const nodes = inorder(root);
10-
const firstNode = nodes.shift()!;
12+
let rightmost = left;
13+
while (rightmost.right !== null) rightmost = rightmost.right;
14+
rightmost.right = cur;
1115

12-
let _root = new TreeNode(firstNode);
13-
const _root_ref = _root;
14-
while (nodes.length !== 0) {
15-
const node = nodes.shift()!;
16-
_root.right = new TreeNode(node);
17-
_root = _root.right;
16+
cur = left;
17+
} else {
18+
prev.right = cur;
19+
prev = prev.right;
20+
cur = cur.right;
21+
}
1822
}
19-
return _root_ref;
23+
24+
return prevRoot.right;
2025
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
function getMinimumDifference(root: TreeNode | null): number {
2+
let ret = Number.MAX_SAFE_INTEGER;
3+
4+
// Let's do the morris traversal
5+
let cur = root;
6+
let prev = Number.MIN_SAFE_INTEGER;
7+
while (cur !== null) {
8+
if (cur.left !== null) {
9+
const left = cur.left;
10+
cur.left = null; // prune
11+
12+
let rightmost = left;
13+
while (rightmost.right !== null) rightmost = rightmost.right;
14+
rightmost.right = cur;
15+
16+
cur = left;
17+
} else {
18+
ret = Math.min(ret, cur.val - prev);
19+
prev = cur.val;
20+
cur = cur.right;
21+
}
22+
}
23+
return ret;
24+
}

src/binary-search-tree/trim-a-binary-search-tree.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@ function trimBST(root: TreeNode | null, low: number, high: number): TreeNode | n
33
if (root.val < low) return trimBST(root.right, low, high);
44
if (root.val > high) return trimBST(root.left, low, high);
55

6-
if (root.right && root.right.val > high) root.right = root.right.left;
7-
if (root.left && root.left.val < low) root.left = root.left.right;
8-
96
root.right = trimBST(root.right, low, high);
107
root.left = trimBST(root.left, low, high);
118
return root;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
const getHeightOf = _.memoize((root: TreeNode | null): number =>
2+
root === null ? 0 : 1 + Math.max(getHeightOf(root.left), getHeightOf(root.right))
3+
);
4+
function isBalanced(root: TreeNode | null): boolean {
5+
return root === null
6+
? true
7+
: isBalanced(root.left) &&
8+
isBalanced(root.right) &&
9+
Math.abs(getHeightOf(root.left) - getHeightOf(root.right)) <= 1;
10+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
function buildTree(preorder: number[], inorder: number[]): TreeNode | null {
2+
if (preorder.length === 0) return null;
3+
4+
const D = preorder.shift()!;
5+
const partitionIdx = inorder.indexOf(D);
6+
7+
const leftInorder = inorder.slice(0, partitionIdx),
8+
rightInorder = inorder.slice(partitionIdx + 1);
9+
10+
const leftPreorder = preorder.slice(0, partitionIdx),
11+
rightPreorder = preorder.slice(partitionIdx);
12+
13+
const root = new TreeNode(D);
14+
root.left = buildTree(leftPreorder, leftInorder);
15+
root.right = buildTree(rightPreorder, rightInorder);
16+
return root;
17+
}
Lines changed: 20 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,27 @@
1+
const getLength = (node: TreeNode | null, direction: "left" | "right"): number =>
2+
node === null ? 0 : getLength(node[direction], direction) + 1;
3+
14
function countNodes(root: TreeNode | null): number {
2-
if (root === null) return 0;
5+
let ret = 0;
36

4-
const getHeight = (node: TreeNode | null): number => {
5-
let height = 0;
6-
let ptr = node;
7-
while (ptr !== null) {
8-
height++;
9-
ptr = ptr.left;
10-
}
11-
return height;
12-
};
13-
const isFullTree = (node: TreeNode | null): boolean => {
14-
if (node === null) return true;
15-
let left = node.left,
16-
right = node.right;
17-
while (left !== null && right !== null) {
18-
left = left.left;
19-
right = right.right;
7+
const backtracking = (node: TreeNode | null = root, prevRes = 1) => {
8+
if (node === null) return;
9+
if (node.left === null && node.right === null) {
10+
ret = prevRes;
11+
return;
2012
}
21-
return left === right; // should be null in same time
22-
};
23-
const traversal = (node: TreeNode | null, lo: number, hi: number): number => {
24-
let mi = Math.floor((lo + hi) / 2);
25-
if (node === null || isFullTree(node)) return hi;
26-
if (!isFullTree(node.right)) return traversal(node.right, mi + 1, hi);
27-
if (!isFullTree(node.left)) return traversal(node.left, lo, mi);
13+
const ll = getLength(node.left, "left"),
14+
lr = getLength(node.left, "right"),
15+
rl = getLength(node.right, "left");
2816

29-
return mi;
17+
if (ll > lr || lr > rl) {
18+
// means left subtree is not full-tree + left is full but last node still in left
19+
backtracking(node.left, prevRes * 2);
20+
} else {
21+
backtracking(node.right, prevRes * 2 + 1);
22+
}
3023
};
3124

32-
const treeHeight = getHeight(root);
33-
return traversal(root, 2 ** (treeHeight - 1), 2 ** treeHeight - 1);
25+
backtracking();
26+
return ret;
3427
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
function delNodes(root: TreeNode | null, to_delete: number[]): (TreeNode | null)[] {
2+
const shouldDelete = _.memoize(
3+
(node: TreeNode | null) => node !== null && to_delete.includes(node.val)
4+
);
5+
const ret: (TreeNode | null)[] = [];
6+
const backtracking = (node: TreeNode | null = root, isRoot = true): void => {
7+
if (node === null) return;
8+
9+
const left = node.left,
10+
right = node.right;
11+
12+
if (shouldDelete(left)) node.left = null;
13+
if (shouldDelete(right)) node.right = null;
14+
15+
if (isRoot && !shouldDelete(node)) ret.push(node);
16+
17+
backtracking(left, shouldDelete(node));
18+
backtracking(right, shouldDelete(node));
19+
};
20+
21+
backtracking(root, true);
22+
23+
return ret;
24+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
function flatten(root: TreeNode | null) {
2+
// morris traversal
3+
let cur = root;
4+
while (cur !== null) {
5+
if (cur.left !== null) {
6+
let right = cur.right;
7+
let left = cur.left;
8+
9+
// prune
10+
cur.left = null;
11+
12+
let rightmost = left;
13+
while (rightmost.right !== null) rightmost = rightmost.right;
14+
rightmost.right = right;
15+
cur.right = left;
16+
}
17+
cur = cur.right;
18+
}
19+
}

src/binary-tree/symmetric-tree.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
const compareSymmetric = (left: TreeNode | null, right: TreeNode | null): boolean => {
2+
if (left === null && right === null) return true;
3+
if (left === null || right === null) return false;
4+
if (left.val !== right.val) return false;
5+
6+
return compareSymmetric(left.left, right.right) && compareSymmetric(left.right, right.left);
7+
};
8+
function isSymmetric(root: TreeNode | null): boolean {
9+
if (root === null) return true;
10+
return compareSymmetric(root.left, root.right);
11+
}

0 commit comments

Comments
 (0)