【数据结构与算法 | 力扣+二叉搜索树篇】力扣450, 98

1. 力扣450:删除二叉搜索树的节点

1. 题目:

给定一个二叉搜索树的根节点 root 和一个值 key ,删除二叉搜索树中的 key对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。

一般来说,删除节点可分为两个步骤:

  1. 首先找到需要删除的节点;
  2. 如果找到了,删除它。

示例 1:

复制代码
输入:root = [5,3,6,2,4,null,7], key = 3
输出:[5,4,6,2,null,null,7]
解释:给定需要删除的节点值是 3,所以我们首先找到 3 这个节点,然后删除它。
一个正确的答案是 [5,4,6,2,null,null,7], 如下图所示。
另一个正确答案是 [5,2,6,null,4,null,7]。

示例 2:

复制代码
输入: root = [5,3,6,2,4,null,7], key = 0
输出: [5,3,6,2,4,null,7]
解释: 二叉树不包含值为 0 的节点

示例 3:

复制代码
输入: root = [], key = 0
输出: []

提示:

  • 节点数的范围 [0, 104].
  • -105 <= Node.val <= 105
  • 节点值唯一
  • root 是合法的二叉搜索树
  • -105 <= key <= 105

进阶: 要求算法时间复杂度为 O(h),h 为树的高度。

2. 题解

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    TreeNode root1;
    public TreeNode deleteNode(TreeNode root, int key) {
        root1 = root;
        TreeNode p = root;
        TreeNode parent = null;
        while (p != null) {
            if (p.val > key) {
                parent = p;
                p = p.left;
            } else if (p.val < key) {
                parent = p;
                p = p.right;
            } else {
                break;
            }
        }
        if (p == null) {
            return root;
        }
        if (p.left == null && p.right == null) {
            shift(parent, p, null);
        } else if (p.left != null && p.right == null) {
            shift(parent, p, p.left);
        } else if (p.left == null && p.right != null) {
            shift(parent, p, p.right);
        } else {
            TreeNode s = p.right;
            TreeNode sParent = p;
            while (s.left != null) {
                sParent = s;
                s = s.left;
            }
            if (p != sParent) {
                shift(sParent, s, s.right);
                s.right = p.right;
            }
            shift(parent, p, s);
            s.left = p.left;
        }

        return root1;
    }
    public void shift(TreeNode parent, TreeNode deleted, TreeNode child) {
        if (parent == null) {
            root1 = child;
        } else if (parent.left == deleted) {
            parent.left = child;
        } else {
            parent.right = child;
        }
    }
}

2. 力扣98 :验证二叉搜索树

1. 题目:

给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。

有效 二叉搜索树定义如下:

  • 节点的左 子树

    只包含小于当前节点的数。

  • 节点的右子树只包含 大于 当前节点的数。

  • 所有左子树和右子树自身必须也是二叉搜索树。

示例 1:

复制代码
输入:root = [2,1,3]
输出:true

示例 2:

复制代码
输入:root = [5,1,4,null,null,3,6]
输出:false
解释:根节点的值是 5 ,但是右子节点的值是 4 。

提示:

  • 树中节点数目范围在[1, 104]
  • -231 <= Node.val <= 231 - 1

2.思路(递归):

对于该题我们可以使用递归的方法去解决。由于二叉搜索树的特性,一个节点比其左孩子的值要大,比右孩子的要小(如果其有左右孩子的话),但由此条件是不够推出其是二叉搜索树的。如果某节点的值满足比其左子树的最大值要大,比其右子树的最小值要小,并且其左孩子和右孩子都满足该规则的话,是可以推出该是一个有效的二叉搜索树的。

3. 题解:

java 复制代码
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isValidBST(TreeNode root) {
        return doisValidBST(root);
    }
    public boolean doisValidBST(TreeNode node) {
        // 如果是空树,直接返回
        if(node == null) {
            return true;
        }
        boolean flag = true;
        TreeNode p = null;
        // 该节点存在左子树的前提下,满足节点比左子树所有节点的最大值要大
        if ((p = node.left) != null) {
            while(p.right != null) {
                p = p.right;
            }
            flag = p.val < node.val ? true : false;
        }
        // 如果flag为false,就不必要进行下列的判断了
        if(flag){
            //在节点存在右子树的前提下,满足节点比右子树的所有节点的最小值要小
            if ((p = node.right) != null) {
            while(p.left != null) {
                p = p.left;
            }
            flag = p.val > node.val ? true : false;
        }
        }
        if(node.left == null && node.right == null) {
            return flag;
        } else if (node.left != null && node.right == null) {
            return flag==true && isValidBST(node.left);
        } else if (node.left == null && node.right != null) {
            return flag && isValidBST(node.right);
        } else {
            return flag && isValidBST(node.left) && isValidBST(node.right);
        }
    }
}

4. 思路(有序递增数列)

由题可知,中序遍历得到的序列一定是递增数列。

5. 题解:

java 复制代码
class Solution {
    Deque<Integer> deque = new LinkedList<>();
    public boolean isValidBST(TreeNode root) {
        midTraverse(root);
        while (!deque.isEmpty()){
            int i1 = deque.pop();
            if(deque.isEmpty()){
                return true;
            }
            int i2 = deque.peek();
            if(i2 >= i1){
                return false;
            }
        }
        return true;
    }
    private void midTraverse(TreeNode node) {
        if (node == null) {
            return;
        }
        midTraverse(node.left);
        deque.push(node.val);
        midTraverse(node.right);
    }
}
相关推荐
一条大祥脚几秒前
Codeforces Round 1072 (Div. 3) 树形背包|线段树二分|区间并查集维护区间合并/set维护区间分裂
算法·深度优先·图论
Xの哲學12 分钟前
Linux SKB: 深入解析网络包的灵魂
linux·服务器·网络·算法·边缘计算
无限进步_15 分钟前
【C语言&数据结构】二叉树遍历:从前序构建到中序输出
c语言·开发语言·数据结构·c++·算法·github·visual studio
CodeByV19 分钟前
【算法题】哈希
算法·哈希算法
独自破碎E22 分钟前
【层序遍历】序列化二叉树
leetcode
天赐学c语言25 分钟前
1.14 - 用栈实现队列 && 对模板的理解以及模板和虚函数区别
c++·算法·leecode
高洁0125 分钟前
AI智能体搭建(3)
人工智能·深度学习·算法·数据挖掘·知识图谱
不知名XL1 小时前
day24 贪心算法 part02
算法·贪心算法
AI科技星1 小时前
时空几何:张祥前统一场论20核心公式深度总结
人工智能·线性代数·算法·机器学习·生活
菜鸟233号1 小时前
力扣518 零钱兑换II java实现
java·数据结构·算法·leetcode·动态规划