Day 22|二叉搜素树(剪枝)

剪枝

上下限递归的主要思路

  • 设每个节点必须在一个范围内: ( m i n , m a x ) (min, max) (min,max),不包含边界,若节点值超过这个范围,则返回 false
  • 对于 node.left 范围肯定是 ( m i n , n o d e . v a l ) (min, node.val) (min,node.val)
  • 对于 node.right 范围肯定是 ( n o d e . v a l , m a x ) (node.val, max) (node.val,max)
  • 一开始不知道 min,max 则取 java 中长整数的最小Long.MIN_VALUE、最大值Long.MAX_VALUE

相关习题:
验证二叉搜索树-力扣 98 题
求范围和-力扣 938 题
满老师这两道题也用了这个思路,叫做上下限递归

Leecode习题

669. 修剪二叉搜索树

方法一:递归

class Solution {
    public TreeNode trimBST(TreeNode node, int low, int high) {
        if(node == null) return null;
        // 不在(删)
        if(node.val<low){
           return trimBST(node.right,low,high);
        }
        if(node.val>high){
           return trimBST(node.left,low,high);
        }
       //在(找到了,删除)
       root.left = trimBST(root.left,low,high);
       root.right = trimBST(root.right,low,high);
       return root;

    }
}

方法二:迭代
1.反反复复处理根节点,直到根节点在目标范围内
2.处理左子树(此时根节点在范围内,所以左边只有小于low)
3.处理右子树(只考虑大于high的情况)

class Solution {
    public TreeNode trimBST(TreeNode root, int low, int high) {
       if(root == null) return null;

       // 处理根节点
       while(root!=null&&(root.val<low||root.val>high)){
        if(root.val<low){
            root = root.right;
        }else{
            root = root.left;
        }
       }

       TreeNode cur = root;
       //处理左子树
       while(cur !=null){
           while(cur.left!=null&&cur.left.val<low){
               cur.left = cur.left.right;
           }
           cur = cur.left;
       }
      // 处理右子树
        cur = root;
       while(cur !=null){
         while(cur.right!=null&&cur.right.val>high){
            cur.right = cur.right.left;
        }
        cur = cur.right;
        }

        return root;
    }
}

108.将有序数组转换为二叉搜索树

二叉搜索树的中序遍历就是有序数组
方法一:递归(分治法)
用二分法,先找到中间节点,前面的就作为左子树,后面就是右子树
三要素:
1.返回值:为了建立新的父子关系
2.停止条件:输入数组长度为1或者不存在了
3.单层循环:中间节点作为根节点,前面的就作为左子树,后面就是右子树

class Solution {
    public TreeNode sortedArrayToBST(int[] nums) {
    return genBST(nums,0,nums.length-1);
    }

    private TreeNode genBST(int[] nums,int l,int r){
        if(l>r) return null;
        if(l==r) return new TreeNode(nums[l]);

        int mid = (l+r)>>1;
        TreeNode root = new TreeNode(nums[mid]);
        root.left = genBST(nums,l,mid-1);
        root.right = genBST(nums,mid+1,r);
        return root;
    }
}

1008 题-根据前序遍历结果构造二叉搜索树

方法一:分治法(同上)满老师解析

关键:找到根节点,以及对应的索引,确定哪一块表示左子树和右子树
上一题通过(l+r)>>2表示中间节点,而这道题一直0是根节点,所以需要通过循环找到比nums[0]小的,确定左子树的范围。

class Solution {
    public TreeNode bstFromPreorder(int[] nums) {
       return genBTS(nums,0,nums.length-1);
    }

    private TreeNode genBTS(int[] nums,int s,int e){
   if(s>e) return null;
  
   TreeNode root = new TreeNode(nums[s]);
   int index = s+1;
   while(index<=e){
       if(nums[index]>nums[s]){
           break;
       }
       index++;
   }
   root.left = genBTS(nums,s+1,index-1);
   root.right = genBTS(nums,index,e);
   return root;
    }
}

538. 把二叉搜索树转换为累加树

方法一:递归

  1. 返回值无(主要用于建立父子关系,若父子关系没变,无需返回值)
  2. 停止条件:root==null
  3. 单层递归逻辑:反中序遍历(右我左),遍历一个节点累加一次
class Solution {
     int sum =0;
    public TreeNode convertBST(TreeNode root) {
       
         revMid(root);
         return root;
    }

    private void revMid(TreeNode root){
        if(root == null) return;
        
        revMid(root.right);
        sum += root.val;
        root.val =sum;
        revMid(root.left);
    }
}

方法二:反中序遍历(右我左)----迭代

class Solution {
    public TreeNode convertBST(TreeNode root) {
     if(root == null) return null;
     int pre =0;
   LinkedList<TreeNode> stack = new LinkedList<>();
    TreeNode cur = root;
    while(cur!=null||!stack.isEmpty()){
        if(cur!=null){
            stack.push(cur);
            cur = cur.right;
        }else{
            cur = stack.pop();
            cur.val +=pre;
            pre = cur.val;
            cur = cur.left;
        }
    }
    return root;
    }
}

总结有关二叉树题型规律

代码随想录得总结:自己也要总结,先欠着

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值