代码随想录算法营|二叉树2

递归函数中,如果不为void的话,在递归的时候需要return左边和右边返回的值

题目十四:最大二叉树

1. 构造二叉树用前序遍历:根左右;左右节点是否有if取决于递归终止条件是否有

2.思路

  • 返回是Treenode构造完二叉树的根节点,传入的是数组
  • 递归终止条件:传入的数组的大小==1也就是到叶子节点了
  • 递归逻辑:
    • 存最大值所在的下标index,最大值value,找到最大值;
    • node.left:index>0保证数组元素个数>=1;左闭右开数组(0,index)也就是从第0个到index之前1个
    • node.rightt:index<nums.size-1保证元素个数>=1;左闭右开数组(index+1,nums.size)
  public TreeNode constructMaximumBinaryTree(int[] nums) {
        return constructMaximumBinaryTree1(nums, 0, nums.length);
    }

    public TreeNode constructMaximumBinaryTree1(int[] nums, int leftIndex, int rightIndex) {
        if (rightIndex - leftIndex < 1) {// 没有元素了
            return null;
        }
        if (rightIndex - leftIndex == 1) {// 只有一个元素
            return new TreeNode(nums[leftIndex]);
        }
        int maxIndex = leftIndex;// 最大值所在位置
        int maxVal = nums[maxIndex];// 最大值
        for (int i = leftIndex + 1; i < rightIndex; i++) {
            if (nums[i] > maxVal){
                maxVal = nums[i];
                maxIndex = i;
            }
        }
        TreeNode root = new TreeNode(maxVal);
        // 根据maxIndex划分左右子树
        root.left = constructMaximumBinaryTree1(nums, leftIndex, maxIndex);
        root.right = constructMaximumBinaryTree1(nums, maxIndex + 1, rightIndex);
        return root;
    }

题目十五:合并二叉树

1. 617. 合并二叉树 - 力扣(LeetCode) :将两个二叉树对应位置的值进行相加合并

2. 思路(更改tree1的结构)

  • 递归方法返回合并完的Treenode,参数是Treenode节点一和Treenode节点二
  • 终止条件:如果tree1是null返回tree2,如果tree2是null返回tree1
  • 递归逻辑:返回对应的根节点的子树给上一层,
    • 中:tree1.val+=tree2.val
    • 左:tree1.left=merge(tree1.left,tree2.left)
    • 右:tree1.right=merge(tree1.right,tree2.right)
 public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
        if(root1==null)return root2;
        if(root2==null)return root1;
        root1.val+=root2.val;
        root1.left=mergeTrees(root1.left,root2.left);
        root1.right=mergeTrees(root1.right,root2.right);
        return root1;
    }

题目十六:二叉搜索树中的搜索

1. 思路:要用result接住下面递归返回的节点

public TreeNode searchBST(TreeNode root, int val) {
        if(root==null || root.val==val)return root;
        TreeNode result=new TreeNode();
        if(root.val>val)result= searchBST(root.left,val);
        if(root.val<val)result= searchBST(root.right,val);
        return result;
    }

题目十七:验证二叉搜索树

1. 题目:98. 验证二叉搜索树 - 力扣(LeetCode) 

2. 思路:如果没有节点也是二叉搜索树,要判断根节点比左子树大,不是单比root.left左孩子

  • TreeNode pre; 声明了一个变量但没有初始化,它默认值为 null设置为全局变量才不会在每次递归的时候被初始化
  • TreeNode pre = new TreeNode(); 声明了一个变量并立即初始化,它指向了一个新创建的 TreeNode 对象
class Solution {
    TreeNode pre;//全局变量不会在每次递归的时候被初始化
    public boolean isValidBST(TreeNode root) {
        if(root==null)return true;
        boolean result1=isValidBST(root.left);//左
        //TreeNode pre=new TreeNode();不正确
        if(pre!=null && pre.val>=root.val)return false;
        pre=root;
        boolean result2=isValidBST(root.right);//右
        return result1&&result2;
    }
}

题目十八:二叉搜索树的最小绝对差

1. 题目:530. 二叉搜索树的最小绝对差 - 力扣(LeetCode) :返回 树中任意两不同节点值之间的最小差值 

2. 思路

(1)要设置全局变量pre和ans,来存储上一个节点和两个节点的差值最小值

(2)递归的时候重新写递归函数,因为最后返回最大值就行,所以void

class Solution {
    TreeNode pre;
    int ans=Integer.MAX_VALUE;
    public int getMinimumDifference(TreeNode root) {
        if(root==null)return 0;
        huisu(root);
        return ans;
    }
    public void huisu(TreeNode cur){
        if(cur==null)return;
        huisu(cur.left);
        if(pre!=null){
            ans=Math.min(ans,cur.val-pre.val);
        }
        pre=cur;
        huisu(cur.right);
    }
}

题目十九:二叉搜索树中的众树

1. 题目:. - 力扣(LeetCode)这里的二叉搜索树可以有很多个众数

2. 思路:二叉搜索树一定是中序遍历

(1)count是统计单个元素出现的频率;maxcount是当前遍历过的最高频率

(2)定义全局变量:pre指针,count,maxcount,int[] res放结果

(3)递归

  • 参数是Treenode cur,返回值是void
  • 终止条件:如果if(cur==null)return null
  • 单层递归逻辑:用中序遍历,左中右
    • 左:huisu(cur.left)
    • 中:如果pre是null,第一个元素,count=1;如果pre和cur相等,count++;如果不相等count=1;统计(如果count==max就把当前的元素放入结果集)
    • 右:huisu(cur.right)
class Solution {
    List<Integer> ans=new ArrayList<>();
    int count;
    int maxcount;
    TreeNode pre=null;
    public int[] findMode(TreeNode root) {
        huisu(root);
        int[] res=new int[ans.size()];
        for(int i=0;i< ans.size();i++){
            res[i]=ans.get(i);
        }
        return res;
    }
    public void huisu(TreeNode cur){
        if (cur==null)return;
        huisu(cur.left);
        if(pre==null )count=1;
        else if(pre.val!= cur.val)count=1;
        else if(pre.val==cur.val)count++;
        pre=cur;
        //处理maxcount
        if(count==maxcount)ans.add(cur.val);
        else if(count>maxcount){
            maxcount=count;
            ans.clear();
            ans.add(cur.val);
        }
        huisu(cur.right);
        return;
    }
}

题目二十:求二叉树的最近公共祖先

1. . - 力扣(LeetCode) :自底向上处理结果,

  • 第一种情况:左右子树只要出现了p或q就往上返回,在根节点进行判断
  • 第二种情况:左孩子和根节点分别是p和q

2. 递归

  • 返回值是Treenode,参数是root,p,q
  • 边界条件:如果root为空,则返回空;如果root.va==pl或者root.val==q,则返回root
  • 递归逻辑:后序,中要根据左和右来判断
    • 左:Treenode left=huisu(root.left,q,p),left表示左子树有没有出现过p或者q
    • 右:Treenode right=huisu(root.right,q,p),left表示右子树有没有出现过p或者q
    • 中:如果left或者right不为空,则root就是最近公共祖先,则返回root
    • 左不为空、右为空返回左;左为空、右不为空返回右;左右都为空则返回null
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root==null)return null;
        if (root==p ||root==q)return root;
        TreeNode left=lowestCommonAncestor(root.left,p,q);//左
        TreeNode right=lowestCommonAncestor(root.right,p,q);//右
        if (left==p && right==q)return root;//中
        else if(left==q && right==p)return root;
        else if (left==null && right!=null)return right;
        else if(left!=null && right==null)return left;
        else return null;//没有找到
    }

题目二十一:二叉搜索树的最近公共祖先

1. 题目:代码随想录 (programmercarl.com) 

2. 思路:如果从上往下遍历的时候,发现一个root的值在p和q中间,则root一定是最近的公共祖先,没有可能是次近的公共祖先,需要用return接住返回的点

  public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode 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;
    }

题目二十二:二叉搜索树中的插入操作

1. 题目:701. 二叉搜索树中的插入操作 - 力扣(LeetCode)

2. 思路:如果遍历到根节点,new一个新的节点并返回;遍历左子树和右子树的时候,用root.left和root.right接住return的点,return的是新的左子树或右子树

 public TreeNode insertIntoBST(TreeNode root, int val) {
        if(root==null){
            TreeNode newnode=new TreeNode(val);
            return newnode;
        };
        if(root.val<val)root.right= insertIntoBST(root.right,val);
        else if(root.val>val)root.left= insertIntoBST(root.left,val);
        return root;
    }

题目二十三:删除二叉搜索树中的节点

1. 题目: 450. 删除二叉搜索树中的节点 - 力扣(LeetCode)

2. 递归:不用去遍历整个二叉树,找到删除的点就终止

  • (1) 返回值是Treenode,参数是root和key
  • (2)边界条件:共五种情况
    • 没有找到要删除的节点:if(root==null)返回空的,没有找到要删除的点
    • 删的是叶子节点,左右不为空:如果左子树和右子树都为空,直接删除return null
    • 删的节点左不为空、右为空:return root.left
    • 删的节点左为空、右不为空:return root.right
    • 删的节点左右都不为空:右孩子继位,原先的左子树放在右孩子的左子树的最下面。首先用cur指向右孩子,然后用while循环找到左子树的最左叶子节点。cur.left=root.left。再return root.right
  • (3)递归逻辑
    • if(val<root.val) root.left=huisu(root.left,key)用root.left接住新的节点
    • if(val>root.val) root.right=huisu(root.right,key)用root.right接住新的节点
  • 最后返回root
public TreeNode deleteNode(TreeNode root, int key) {
        //边界条件
        if(root==null)return null;//1.不存在
        if(root.val==key){
            //2.是叶子节点
            if (root.left==null && root.right==null)return null;
            //3.左不为空、右为空
            else if (root.left!=null && root.right==null)return root.left;
            //4.右不为空,左为空
            else if (root.left==null && root.right!=null)return root.right;
            //5.左右都不为空
            else{//找到最左叶子节点
                TreeNode cur=root.right;
                while (cur.left!=null)cur=cur.left;
                cur.left=root.left;
                return root.right;
            }
        }
        //递归逻辑
        if(root.val<key)root.right=deleteNode(root.right,key);
        if(root.val>key)root.left=deleteNode(root.left,key);
        return root;
    }

题目二十四:修剪二叉搜索树

1.669. 修剪二叉搜索树 - 力扣(LeetCode) 

2. 递归思路:根左右

  • 返回值是Treenode,参数是边界值low、high
  • 终止条件:if(root==null) return null
  • 递归思路: if(root.val<low)huisu(root.right,left,right)去修建root的右子树,将修剪好树的新的根节点返回
  public TreeNode trimBST(TreeNode root, int low, int high) {
        if (root==null)return null;//边界条件
        if (root.val<low)return trimBST(root.right,low,high);//1.处理根
        if (root.val>high)return trimBST(root.left,low,high);
        root.left=trimBST(root.left,low,high);//2.左
        root.right=trimBST(root.right,low,high);//3.右
        return root;
    }

题目二十五:将有序数组转化为二叉搜索树

1. 题目:108. 将有序数组转换为二叉搜索树 - 力扣(LeetCode)

2. 思路:找到中间的点作为根节点,当数组长度是偶数的时候取左节点右节点都可以

  • 返回值是Treenode也就是构造好的二叉搜索树,参数是int数组,left,right(左闭右闭)
  • 终止条件:if(left>right)return null,当left=right的时候是只有一个元素是合法区间
  • 单层递归:mid=(left+right)/2取下,构造二叉树
public TreeNode sortedArrayToBST(int[] nums) {
        if(nums.length==0)return null;
        return huisu(nums,0,nums.length-1);
    }
    public TreeNode huisu(int[] nums,int left,int right){//左闭右闭
        if(left>right)return null;//边界条件
        int mid=(left+right)/2;//中
        TreeNode root=new TreeNode(nums[mid]);
        root.left=huisu(nums,left,mid-1);//左
        root.right=huisu(nums,mid+1,right);//右
        return root;
    }

题目二十六:把二叉搜索树转化为累加树

1. 题目:538. 把二叉搜索树转换为累加树 - 力扣(LeetCode) 前一个结点的更新值和本节点相加

2. 从后往前倒序相加:右中左,定义pre是前一个结点的数值,初始化为0

  • 返回值是void,参数是Treenode cur
  • 终止条件:if(cur==null)return;
  • 递归逻辑:
    • 右:huisu(cur.right)
    • 中:cur.val+=pre;pre=cur.val
    • 左:huisu(cur.left)
class Solution {
    int pre=0;
    public TreeNode convertBST(TreeNode root) {
       huisu(root);
       return root;
    }
    public void huisu(TreeNode cur){
        if(cur==null)return;
        huisu(cur.right);
        cur.val+=pre;
        pre=cur.val;
        huisu(cur.left);
    }
}

  • 21
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值