二叉搜索树BST操作合集(判断合法性\查找\插入\删除等等)

本文详细介绍了二叉搜索树的基本概念及其性质,包括如何判断一棵树是否为有效的二叉搜索树,以及在二叉搜索树上进行加一操作、查找、插入和寻找两个数之和的操作。通过递归和迭代两种方法展示了具体实现,并提供了LeetCode相关问题的解决方案。
摘要由CSDN通过智能技术生成

二叉树算法设计总路线

明确一个节点要做什么事情,然后剩下的事情交给递归框架

void traverse(TreeNode root) {
	// root 需要做什么
	// 剩下的交给递归
	traverse(root.left);
	traverse(root.right);
}

先拿两个二叉树操作练手

一、二叉树 中每个节点的值加一 (二叉树操作)

void plusOne(TreeNode root) {
	if (root == null) return;
	root.val += 1;
	
	plusOne(root.left);
	plusOne(root.right);
}

二、判断两颗二叉树 是否完全相同 (二叉树操作)

boolean isSameTree(TreeNode root1, TreeNode root2) {
	// 如果同时为空,显然相同
	if (root1 == null && root2 == null) return true;
	// 如果不同时为空,则显然不相同
	if (root1 == null || root2 == null) return false;
	// 如果两节点值不同,显然不相同
	if (root1.val != root2.val) return false;
	
	// 当前root1和root2值相同,比较完毕,接下来判断其左右子树
	return isSameTree(root1.left, root2.left) && isSameTree(root1.right, root2.right);
}

二叉搜索树介绍

定义:一个二叉树中,任意节点的值要大于等于左子树所有节点的值,且要小于等于右子树的所有节点的值。
有效 二叉搜索树定义如下:

  1. 节点的左子树只包含 < 当前节点的数。
  2. 节点的右子树只包含 > 当前节点的数。
  3. 所有左子树和右子树自身必须也是二叉搜索树。

LeetCode 98. 判断BST的合法性

在这里插入图片描述

思路

root需要做的是要和其整个左子树和右子树作比较,值要大于等于左子树所有节点的值,且要小于等于右子树的所有节点的值
使用辅助函数,增加函数列表boolean isValidBST(TreeNode root, TreeNode min, TreeNode max); 这样相当于给子树上的所有节点添加了一个min和max边界,约束root的左子树节点值不超过root的值, 右子树节点值不小于root的值

代码实现(java)

boolean isValidBST(TreeNode root) {
	return isValidBST(root, null, null);
}

boolean isValidBST(TreeNode root, TreeNode min, TreeNode max) {
	// 成功到达叶子节点,说明过程都合法,返回true
	if (root == null) return true;
	// 如果有min, 且当前root节点值小于min的值,说明不符合二叉搜索树,返回false
	if (min != null && root.val <= min.val) return false;
	// 如果有max, 且当前root节点值大于max的值,说明不符合二叉搜索树,返回false
	if (max != null && root.val >= max.val) return false;
	
	// 当前节点判断完毕,接着判断左子树和右子树
	// 左子树中较小值为空,较大值则为其父节点
	// 右子树中较大值为空,较小值则为其父节点
	return isValidBST(root.left, min, root) && isValidBST(root.right, root, max);
}

LeetCode 700. 二叉搜索树中的搜索

在这里插入图片描述

思路

递归思路:
利用二叉搜索树的特性,左小右大

  • 当根节点值比val值大时,去左子树找
  • 当根节点值比val值小时,去右子树找
  • 当根节点值等于val值时,返回给节点

迭代思路:
循环寻找值为val的节点,判断依据为:

  • 当根节点值比val值大时,让根节点等于左孩子,继续找
  • 当根节点值比val值小时,让根节点等于右孩子,继续找
  • 结束迭代的条件为 root == null(没找到)、root.val == val(找到了)
  • 最终返回root,没找到就为null,找到了则为root为根的子树

代码实现(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 TreeNode searchBST(TreeNode root, int val) {
        // 递归
        if(root == null || root.val == val) return root;
        return root.val > val ? searchBST(root.left, val) : searchBST(root.right, val);


        // 迭代
        // while(root != null && root.val != val) {
        //     root = root.val > val ? root.left : root.right;
        // }
        // return root;
    }
}

LeetCode 701. 二叉搜索树中的插入操作

在这里插入图片描述

思路

整体的思路就是:遍历二叉搜索树,找到空节点 插入元素就可以了(不考虑改变树结构)
递归思路:
利用二叉搜索树的特性,左小右大

  • 当根节点值比val值大时,去左子树找
  • 当根节点值比val值小时,去右子树找
  • 当根节点值为空时,创建新节点插入

迭代思路:
利用二叉搜索树的特性,左小右大

  • 当根节点值比val值大时,去左子树找
  • 当根节点值比val值小时,去右子树找
  • 最终找到要插入的叶子结点位置,然后判断val的值和该叶子结点的值的大小关系,最终插入即可

代码实现(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 TreeNode insertIntoBST(TreeNode root, int val) {
        // 迭代  迭代寻找空叶子结点
        if(root == null) return new TreeNode(val);
        TreeNode resRoot = root; // 记录根节点
        TreeNode prev = root; // 记录叶子结点
        // 寻找要插入的叶子结点
        while(root != null) {
           prev = root;
           if(root.val > val) {
               root = root.left;
           } else {
               root  = root.right;
           }
        }
        // 判断要插在叶子结点的左孩子还是右孩子
        if(val > prev.val) prev.right = new TreeNode(val);
        else prev.left = new TreeNode(val);

        return resRoot;

        // 递归   递归寻找空叶子结点
        // if(root == null) return new TreeNode(val);
        // if(root.val > val) root.left = insertIntoBST(root.left, val);
        // else root.right = insertIntoBST(root.right, val);
        // return root;
    }
}

LeetCode 653. 两数之和 IV - 输入 BST

在这里插入图片描述

思路

中序遍历 + 双指针
最简单的思路:题目给出的是二叉搜索树,所以中序遍历可以得到排序好的集合(数组),然后使用双指针,找和为k即可

哈希表 + 深度优先遍历
使用哈希表记录遍历到的节点,判断当前哈希表中,是否包含k - 当前节点的值,如果存在,说明这两个值加起来就是k,返回true,如果最终遍历结束都没有找到,说明不存在,返回false

代码实现(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 {
    // 深度优先搜索 + 哈希表
    Set<Integer> set = new HashSet<>();
    public boolean findTarget(TreeNode root, int k) {
        if(root == null) return false;
        if(set.contains(k - root.val)) return true;
        set.add(root.val);
        return findTarget(root.left, k) || findTarget(root.right, k);
    }

    // 中序遍历 + 双指针
    // List<Integer> list = new ArrayList<>();
    // public boolean findTarget(TreeNode root, int k) {
    //     inorder(root);
        
    //     int left = 0;
    //     int right = list.size() - 1;
    //     while(left < right) {
    //         int sum = list.get(left) + list.get(right);
    //         if(sum == k) return true;
    //         else if(sum < k) left++;
    //         else right--;
    //     }
    //     return false;
    // }

    // public void inorder(TreeNode node) {
    //     if(node == null) return;
    //     inorder(node.left);
    //     list.add(node.val);
    //     inorder(node.right);
    // }
}

LeetCode 235. 二叉搜索树的最近公共祖先

在这里插入图片描述

思路

根据题意可以知道,p和q是在其公共父节点的两端的,所以我们可以进行判断

  • 如果p和q都小于 root, 说明p和q都在其左子树,递归到左子树 root.left
  • 如果p和q都大于 root, 说明p和q都在其右子树,递归到左子树 root.right
  • 当发现前两个条件都不满足,说明p和q在root节点的左右子树上,即root就是最近公共父节点,返回即可

代码实现(java)

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */

class Solution {
    TreeNode res = null;
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        // p 和 q 在某个节点的两端, 如果找到既不同时大,也不同时小的节点,就是二者的最近公共父节点
        if(root.val > p.val && root.val > q.val) return lowestCommonAncestor(root.left, p, q);
        if(root.val < p.val && root.val < q.val) return lowestCommonAncestor(root.right, p, q);
        return root;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值