diff --git a/README.md b/README.md index bfba8c7..2b381cd 100644 --- a/README.md +++ b/README.md @@ -196,9 +196,10 @@ Ace Coding Interview with 75 Qs | Binary Search Tree | | | | ----------------------------------- | --------------- | ------ | | 700. Search in a Binary Search Tree | [Solution][700] | Easy | -| 450. Delete Node in a BST | Solution | Medium | +| 450. Delete Node in a BST | [Solution][450] | Medium | [700]: ./src/page-7/700.%20Search%20in%20a%20Binary%20Search%20Tree/searchBST.ts +[450]: ./src/page-5/450.%20Delete%20Node%20in%20a%20BST/deleteNode.ts | Graphs - DFS | | | | ------------------------------------------------------------ | -------- | ------ | diff --git a/src/page-5/450. Delete Node in a BST/deleteNode.test.ts b/src/page-5/450. Delete Node in a BST/deleteNode.test.ts new file mode 100644 index 0000000..45a0647 --- /dev/null +++ b/src/page-5/450. Delete Node in a BST/deleteNode.test.ts @@ -0,0 +1,27 @@ +import { stringify } from 'flatted'; + +import { generateBinaryTree } from '~/utils/binary-tree'; + +import { deleteNode } from './deleteNode'; + +describe('450. Delete Node in a BST', () => { + test('deleteNode', () => { + { + const root = generateBinaryTree([5, 3, 6, 2, 4, null, 7]); + const expected = generateBinaryTree([5, 4, 6, 2, null, null, 7]); + expect(stringify(deleteNode(root, 3))).toBe(stringify(expected)); + } + + { + const root = generateBinaryTree([5, 3, 6, 2, 4, null, 7]); + const expected = generateBinaryTree([5, 3, 6, 2, 4, null, 7]); + expect(stringify(deleteNode(root, 0))).toBe(stringify(expected)); + } + + { + const root = generateBinaryTree([]); + const expected = generateBinaryTree([]); + expect(stringify(deleteNode(root, 0))).toBe(stringify(expected)); + } + }); +}); diff --git a/src/page-5/450. Delete Node in a BST/deleteNode.ts b/src/page-5/450. Delete Node in a BST/deleteNode.ts new file mode 100644 index 0000000..beaaa4a --- /dev/null +++ b/src/page-5/450. Delete Node in a BST/deleteNode.ts @@ -0,0 +1,50 @@ +import type { TreeNode } from '~/utils/binary-tree'; + +type DeleteNode = (root: TreeNode | null, key: number) => TreeNode | null; + +/** + * Accepted + */ +export const deleteNode: DeleteNode = (root, key) => { + // Base case: If the root is null, the tree is empty, or we've reached a leaf node. + if (root === null) return null; + + // If the key to be deleted is less than the current node's value, + // search in the left subtree. + if (key < root.val) { + root.left = deleteNode(root.left, key); + return root; // Return the unchanged root after deletion in the left subtree. + } + + // If the key to be deleted is greater than the current node's value, + // search in the right subtree. + if (key > root.val) { + root.right = deleteNode(root.right, key); + return root; // Return the unchanged root after deletion in the right subtree. + } + + // If the key matches the current node's value, this is the node to be deleted. + + // Case 1: Node has no left child, return the right child. + if (root.left === null) return root.right; + + // Case 2: Node has no right child, return the left child. + if (root.right === null) return root.left; + + // Case 3: Node has two children. + // Find the inorder successor (smallest node in the right subtree). + let minNode = root.right; + + while (minNode.left !== null) { + minNode = minNode.left; // Traverse to the leftmost node. + } + + // Replace the current node's value with the inorder successor's value. + root.val = minNode.val; + + // Delete the inorder successor node (which is guaranteed to have at most one child). + root.right = deleteNode(root.right, minNode.val); + + // Return the root of the updated tree. + return root; +};