5. 泛型递归、树的递归

树的面试题解法一般都是递归,因为

  1. 结点的定义就是以递归方式进行
  2. 重复性(自相似性)
    二叉搜索树:左子树小于根节点,右子树大于根节点,且左右子树具有相同特征

1 递归( recursion)

本质类似于循环,通过循环体进行
现实生活中的重复性
电影盗梦空间:

  1. 向下进入不同的梦境,向上回到原来的一层
  2. 通过声音同步回到上一层
  3. 每一层的内容都是一份拷贝,主角(参数)进入不同层次梦境(发生并携带变化)后,再一层层返回

1.1 简单的递归

在这里插入图片描述

1.2 递归的代码模板

python

在这里插入图片描述

java

在这里插入图片描述

1.3 思维要点

  1. 不要进行人肉递归(不画递归的状态树)
  2. 找到最近最简单的方法,拆解成可重复解决的问题(最近重复子问题)
  3. 数学归纳法思维(最开始的条件成立,证明n成立n+1也能成立)

2 算法题解

1)22. 括号生成

  • [22] 括号生成
  • 通过递归的方式,类似于树
  • 记录left括号和right括号的个数
  • left保持继续添加,right在小于left的时候添加并继续调用函数
  • 这样会形成满足条件的树状结构
  • 参数left right string res 都是携带改变状态进行传递的
import java.util.ArrayList;

/*
 * @lc app=leetcode.cn id=22 lang=java

 * 
 * 
 */

// @lc code=start
class Solution {
    public List<String> generateParenthesis(int n) {
        List<String> res = new ArrayList<>();
        generate(0, 0, n, "", res);
        return res;
    }

    public void generate(int left, int right, int n, String string, List<String> res){
        if (left == n && right == n) {
            res.add(string);
            return;
        }

        if (left < n) generate(left+1, right, n, string+"(", res);
        if (right < left) generate(left, right+1, n, string+")", res);
    }
}
// @lc code=end


2)[236] 二叉树的最近公共祖先

import org.graalvm.compiler.debug.CSVUtil.Escape;

import jdk.nashorn.api.tree.BinaryTree;

/*
 * @lc app=leetcode.cn id=236 lang=java
 *
 * [236] 二叉树的最近公共祖先
 */

// @lc code=start
/**
 * 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) {
        // 终止条件:找到返回root, 直到 没有子树也找不到就返回null(root.left/right == null)
        // 由上一层的 left/right 接收这层的返回值
        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;
        // 此时右子树没有q/p,就在左子树找q/p
        else if (right == null) return left;
        //root.left 和 root.right两个子树都有,那就返回这两个子树的根root
        else return root;
    }
}
// @lc code=end


图解

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

发布了90 篇原创文章 · 获赞 4 · 访问量 1434

猜你喜欢

转载自blog.csdn.net/weixin_44145258/article/details/103649657
今日推荐