算法——递归

二叉树是用来训练递归的好题目。
你要相信你函数的定义(因为这是你自己写的根据当前节点所做的所有操作,那递归调用当然可以信赖)。写好这个函数签名也是很有意义的工作,一般题目给的够用了,但是有时候返回的数据其实是不够看的,或者方法参数给的也不够用,这时候就需要我们自定义,比如1373.二叉搜索子树的最大键值和(困难),这题我们采用后续遍历的方法,需要的参数很多,所以返回值用的是一个数组,当然你用的爽了,自己这个节点也要写出来对应的确定返回值方法,不能光用不给,没这个道理,递归也不能用。

函数的作用也需要好好斟酌,比如返回最近公共祖先,明面上是返回最近公共祖先节点,但是你调用此方法的时候,想过对左右节点调用,最近公共祖先没有在左节点,左子树下只有一个值怎么办,你也要返回呀,所以遇到值为p或者q的时候也要返回,也对应root节点为p或者q的时候,直接返回。
关于函数签名再多说两句,以二叉搜索树的合法性为例,其参数除了root,还有min和max,这些在第一个节点和最后一个都没用到,第一个节点没有父节点,min、max都是null,而最后一个本身为null,也就直接返回了,那我考虑节点的功能,因为第一个和最后一个一般比较具有代表性,在这时候就不够了,需要考虑其他节点了,这种想法要记着。你考虑的是节点的功能完备,不要局限于特定节点带来的好处而思维受限,想想正常的节点也挺好的。

  1. 写出base case(思路主要在最后一个方法调用的节点(傻傻的走完全程结束条件)以及第一个节点正常需要的操作,此外考虑是否需要提前结束递归,也可能不用傻傻的到最后一个节点,走完全程才结束,有可能需要提前结束(比如二叉树的序列化与反序列化,读到#符号,就可以return了))。首先思路来到递归方法调用的最后一个节点,写出整个方法的终止条件,不能让他无休止的调用下去。有时候也要思路回到第一个节点,先序遍历,直接写出这个节点需要的操作,他并不依赖后续left、right的结果;有时候写需不需要调用递归,比如寻找最近公共祖先,如果这个节点等于p或者q,根本不需要调用后续的递归方法,直接提前结束了。
  2. 这时候开始调用递归方法,相信你的递归,你自己写的方法,只要够完备,对这个节点管用,那对下一个也管用
  3. 写出后续遍历的操作,此时你已经有了左右子节点的返回数据,直接对此进行操作。

236.二叉树的最近公共祖先
在这里插入图片描述

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    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 == null){
            return right;
        }        
        if(right == null){
            return left;
        }
        return root;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值