leetcode 二分搜索树

二分搜索树

二分搜索树势一颗典型的二叉树,二分搜索树根节点的值大于左孩子节点的值,小于右孩子节点的值,插入/删除/查找的时间复杂度都是log(n)

二叉搜索树的创建,插入,删除

创建,插入
 /**
 * 思路:
 * 首先初始化第一个节点,然后第二个节点要插入树中需要找到要插入位置的根节点,
 * 有一个查找的过程,然后根据值的大小分别放在左右子树
 * @param a
 * @param n
 * @return
 */
public static BST create(int [] a,int n) {

    BST root = new BST(a[0]);
    for (int i = 1; i < n; i++) {
        BST searchNode = search(root,a[i]);
        if (searchNode.val > a[i]) {
            searchNode.left = new BST(a[i]);
        }else  if (searchNode.val < a[i]) {
            searchNode.right = new BST(a[i]);
        }
    }
    return root;
}

public static BST search(BST root,int val) {

    if (root == null) {
        return null;
    }
    if (val > root.val && root.right != null) {
        return search(root.right,val);
    }

    if (val < root.val && root.left != null){
        return search(root.left,val);
    }
    return root;
}
删除
/**
*思路:
*1.如果要删除的节点是叶节点,找到要删除节点的父亲节点,直接删除
*2.如果要删除的节点只有左子树,或者右子树,父亲节点指向孩子的左节点或者右节点
*3.如果要删除的节点有左右子树,找到删除的节点的右子树的最左节点,替换到该节点
*/
 public static BST searchParent(BST root,int val) {

    if (root == null) {
        return null;
    }

    if (root.left != null && root.val > val){
        if (root.left.val == val ) {
            return root;
        }
        return searchParent(root.left,val);
    }

    if (root.right != null && root.val < val){
        if (root.right.val == val ) {
            return root;
        }
        return searchParent(root.right,val);
    }
    return null;
}

public static boolean deleteNode(BST root,int val) {

    //找到父亲节点
    BST searchNode = searchParent(root,val);
    if (searchNode == null) {
        return false;
    }
    //找到要删除的节点
    BST deleteNode = null;
    boolean isLeftCHilde = false;
    if (searchNode.left != null && searchNode.left.val == val) {
        deleteNode = searchNode.left;
        isLeftCHilde = true;
    }

    if (searchNode.right != null && searchNode.right.val == val) {
        deleteNode = searchNode.right;
    }
    if (deleteNode.left == null && deleteNode.right == null) {
        //要删除的节点无孩子节点
        if (isLeftCHilde) {
            searchNode.left = null;
        }else {
            searchNode.right = null;
        }

    }else if (deleteNode.left != null && deleteNode.right == null)  {
        //要删除的节点只有左孩子节点
        if (isLeftCHilde) {
            searchNode.left = deleteNode.left;
        }else {
            searchNode.right = deleteNode.left;
        }
    }else if (deleteNode.left == null && deleteNode.right != null)  {
        //要删除的节点只有右孩子节点
        if (isLeftCHilde) {
            searchNode.left = deleteNode.right;
        }else {
            searchNode.right = deleteNode.right;
        }
    }else {
        //要删除的节点有左,右孩子节点
        BST mLeftNode = searchML(deleteNode.right);
        deleteNode.val = mLeftNode.val;
        return deleteNode(deleteNode.right,mLeftNode.val);
    }
    return true;
}

判定一棵树是否是二分搜索树

/**
* 98. Validate Binary Search Tree
* 判定一棵树是否是二分搜索树
* 思路:
* 二分搜索树的判定原则:
* 根节点>左子树
* 根节点 <右子树
*
* 注意:递归的时候,有个隐含条件:
* 左子树的右孩子节点是要小于根节点的
* 右子树的左孩子节点是要大于根节点的
* @param root
* @return

  public boolean isValidBST(TreeNode root) {

    return isValidBST(root,null,null);
}

public boolean isValidBST(TreeNode root,Integer max,Integer min) {

    if (root == null) {
        return true;
    }
    if (max != null && root.val > max) {
        return false;
    }
    if (min != null && root.val < min) {
        return false;
    }
    return isValidBST(root.left,root.val,min) && isValidBST(root.right,max,root.val);
}

求二分搜索树最小公共祖先

/**
* 求最小公共祖先
* 根据二分搜索树的特点:
* 根节点的值大于>左子树的值
* 根节点的值大于<右子树的值
* 如果:
* 两个节点的值在根节点的两边,或者其中一个等于根节点,等于那么最小公共祖先就是根节点
* 如果在一边,则去子树中继续寻找
*
* @param root
* @param p
* @param q
* @return
*/

public TreeNode lowestCommonAncestor1(TreeNode root, TreeNode p, TreeNode q) {

    if (root == null || p == null || q == null) {
        return null;
    }
    //左子树寻找
    if (root.val > p.val && root.val >q.val) {
        return lowestCommonAncestor1(root.left,p,q);
    }

    if (root.val < p.val && root.val <q.val) {
        return lowestCommonAncestor1(root.right,p,q);
    }
    return root;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值