题目描述
解题思路
递归法
- 确定递归函数参数以及返回值
说道递归函数的返回值,在搜索树中的插入操作(opens new window)中通过递归返回值来加入新节点, 这里也可以通过递归返回值删除节点。
- 确定终止条件
遇到空返回,其实这也说明没找到删除的节点,遍历到空节点直接返回了
- 单层处理逻辑
- 第一种情况:没找到删除的节点,遍历到空节点直接返回了
- 找到删除的节点
- 第二种情况:左右孩子都为空(叶子节点),直接删除节点, 返回NULL为根节点
- 第三种情况:删除节点的左孩子为空,右孩子不为空,删除节点,右孩子补位,返回右孩子为根节点
- 第四种情况:删除节点的右孩子为空,左孩子不为空,删除节点,左孩子补位,返回左孩子为根节点
- 第五种情况:左右孩子节点都不为空,则将删除节点的左子树头结点(左孩子)放到删除节点的右子树的最左面节点的左孩子上,返回删除节点右孩子为新的根节点。
第五种情况:
public TreeNode deleteNode(TreeNode root, int key) {if (root == null) {return null;}if (root.val == key) {// 情况一:左为空,右不为空if (root.left == null && root.right != null) return root.left;// 情况二:左不为空,右为空else if (root.left != null && root.right == null) return root.right;// 情况三:左右都为空,直接删除else if (root.left == null && root.right == null) return null;// 情况四:左右都不为空,那么左节点放到右节点的最左边的节点else {// 找到右子树的最左边的节点TreeNode cur = root.right;while (cur.left != null) {cur = cur.left;}// 赋值过去cur.left = root.left;// 删除该节点,返回右子树root = root.right;return root;}}// 根据二叉搜索树的性质进行递归,并接收返回值if (root.val > key) root.left = deleteNode(root.left, key);if (root.val < key) root.right = deleteNode(root.right, key);return root;}
迭代法
// 迭代法public TreeNode deleteNode(TreeNode root, int key) {if (root == null) {return null;}TreeNode pre = null;TreeNode cur = root;while (cur != null) {if (cur.val == key) break;// 一定放在break后面,因为pre是cur的父节点pre = cur;if (cur.val > key) cur = cur.left;else if (cur.val < key) cur = cur.right;}if (pre == null) {return deleteNodes(cur);}// 得知道是删除那个节点(也就是知道cur是pre的左节点还是右节点)if (pre.left != null && pre.left.val == key) {pre.left = deleteNodes(cur);}if (pre.right != null && pre.right.val == key) {pre.right = deleteNodes(cur);}return root;}// 删除节点的4种情况(迭代的删除节点)public TreeNode deleteNodes(TreeNode target) {if (target == null) return target;if (target.left == null) return target.right;if (target.right == null) return target.left;TreeNode cur = target.right;while (cur.left != null) {cur = cur.left;}cur.left = target.left;return target.right;}
