70. 爬楼梯

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

注意:给定 n 是一个正整数。

示例 1:

输入: 2

输出: 2

解释: 有两种方法可以爬到楼顶。

  1. 1 阶 + 1 阶
  2. 2 阶

    示例 2:

输入: 3

输出: 3

解释: 有三种方法可以爬到楼顶。

  1. 1 阶 + 1 阶 + 1 阶
  2. 1 阶 + 2 阶
  3. 2 阶 + 1 阶

思路

//动态规划 二维矩阵
//递归,即斐波那契数列 可以有以下四个解法
//找最近重复性???

solution1 傻递归

//45阶时超时
class Solution {
public int climbStairs(int n) {
if (n<=2) return n;
else return climbStairs(n-1) + climbStairs(n-2);
}
}

solution2 迭代

class Solution {
public int climbStairs(int n) {
if (n<=2) return n;
int a = 1,b=2;
while(n-->2){ //运行与后面的数的差次数
int sum= a + b;
a = b;
b = sum;
}
return b;
}
}

solution3 高级递归

//自顶向下 对计算过的进行保存
class Solution {
int[] cache = new int[100];
public int climbStairs(int n) {
if (n<=2) return n;
else if (cache[n] != 0) return cache[n];
else return cache[n] = climbStairs(n-1) + climbStairs(n-2);
}
}

solution3 动态规划

//从下到上至要抵达的台阶
class Solution {
public int climbStairs(int n) {
int[] cache = new int[n+1];
cache[1] = 1;
cache[0] = 1;
for (int i = 2;i<=n;i++){
cache[i] = cache[i-1]+cache[i-2];
}
return cache[n];
}
}

22. 括号生成

数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

示例:

输入:n = 3

输出:[

"((()))",

"(()())",

"(())()",

"()(())",

"()()()"

]

思路

//递归 不断生成左右括号
//递归1 生成全部情况,过滤掉不合法的情况
//递归2 一边生成符号,一边保留格式正常的
//找最小重复性

solution 1

class Solution {
private List<String> result;
public List<String> generateParenthesis(int n) {
result = new ArrayList<>();
_generate(0, 2*n, "");
return result;
}
private void _generate(int curr,int n,String s){
//停止递归
if (curr == n) {
_filter(s);
return; }
//当前层
//下一层
_generate(curr+1,n,s+'(');
_generate(curr+1,n,s+')');
}
private void _filter(String s){
Stack<Character> st = new Stack<>();
for (char c : s.toCharArray()){
if(c == '(') st.push(c);
else {
if (!st.isEmpty()){
st.pop();
}else {
return;
}
}
}
if (st.isEmpty()) result.add(s);
}
}

solution 2

class Solution {
private List<String> result;
public List<String> generateParenthesis(int n) {
result = new ArrayList<>();
_generate(0,0,n,"");
return result;
}
private void _generate(int left,int right,int n,String s){
//抵达最后一层,停止递归
if (left == n && right == n) {
result.add(s);
return;
}
//当前层
//下一层
// 左括号数量大于右括号数量时,添加右括号
if (left < n) {
_generate(left+1,right,n,s+'(');
}
if (left > right) {
_generate(left,right+1,n,s + ")");
} }
}
class Solution {
public List<String> generateParenthesis(int n) {
List<String> result = new ArrayList<>();
_generate(result,0,0, 2*n, "");
return result;
}
private void _generate(List<String> result,int left,int right,int max,String s){
if (s.length() == max) {
result.add(s);
return; }
if (left < max/2) _generate(result,left+1,right,max,s+'(');
if (right < left) _generate(result,left,right+1,max,s+')');
}
}

98. 验证二叉搜索树

给定一个二叉树,判断其是否是一个有效的二叉搜索树。

假设一个二叉搜索树具有如下特征:

节点的左子树只包含小于当前节点的数。

节点的右子树只包含大于当前节点的数。

所有左子树和右子树自身必须也是二叉搜索树。

示例 1:

输入:

2

/

1 3

输出: true

示例 2:

输入:

5

/

1 4

/

3 6

输出: false

解释: 输入为: [5,1,4,null,null,3,6]。

根节点的值为 5 ,但是其右子节点值为 4 。

错误思路

//没有考虑是整个子树的比较而不只是结点的比较
class Solution {
public boolean isValidBST(TreeNode root) {
if (root == null) return true;
//终止条件
if (root.left == null && root.right == null) return true;
//当前层
if (root.left != null && root.left.val >= root.val) return false;
if (root.right != null && root.right.val <= root.val) return false;
return isValidBST(root.left) && isValidBST(root.right);
}
}

思路整理

//思路1:传入根结点进入递归(错) 传入结点对应树的最小和最大值(对)
//思路2:中序遍历为升序即true

solution1递归

class Solution {
public boolean isValidBST(TreeNode root) {
return helper(root,null,null);
}
public boolean helper(TreeNode root,Integer low,Integer up){
//终止层
if (root == null) return true;
//当前层
if (low!=null && root.val <= low) return false;
if (up!=null && root.val >= up) return false;
//下一层
return helper(root.left,low,root.val) && helper(root.right,root.val,up);
}
}

solution2 中序遍历

class Solution {
public boolean isValidBST(TreeNode root) {
Stack<TreeNode> st = new Stack<>();
double inorder = -Double.MAX_VALUE;
while(!st.isEmpty() || root != null){
while(root!=null){
st.push(root);
root = root.left;
}
root = st.pop();
if (root.val <= inorder) return false;
inorder = root.val;//取左子树为最小值
root = root.right;//遍历右子树
}
return true;
}
}
// 甜姨解法
class Solution {
long pre = Long.MIN_VALUE;
public boolean isValidBST(TreeNode root) {
if (root == null) return true;
//访问左子树(递归到底)
if (!isValidBST(root.left)) return false;
//访问当前结点
if (root.val<=pre) return false;
pre = root.val;
//访问右子树
return isValidBST(root.right); }
}

104. 二叉树的最大深度

给定一个二叉树,找出其最大深度。

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

说明: 叶子节点是指没有子节点的节点。

示例:

给定二叉树 [3,9,20,null,null,15,7],

3

/

9 20

/

15 7

返回它的最大深度 3 。

思路

//递归1、(如果有子树就加1并递归下一层)
//迭代1 深度优先
//迭代2 广度优先

solution1 递归

class Solution {
public int maxDepth(TreeNode root) {
if (root == null) return 0;
return helper(root,1);
}
public int helper(TreeNode root,int max) {
if (root.left == null && root.right == null) return max;
//当前层 和下一层
int left = 0;
int right = 0;
if (root.left != null) left = helper(root.left, max+1);
if (root.right != null) right = helper(root.right,max+1);
return Math.max(right,left); }
}
//简洁版
class Solution {
public int maxDepth(TreeNode root) {
if (root == null) return 0;
else {
int left = maxDepth(root.left);
int right = maxDepth(root.right);
return Math.max(left,right)+1;
}
}
}
// 无敌版
class Solution {
public int maxDepth(TreeNode root) {
return root == null?0:Math.max(maxDepth(root.right),maxDepth(root.left))+1;
}
}

solution2 迭代

class Solution {
public int maxDepth(TreeNode root) {
TreeNode node = root;
Stack<TreeNode> nodest = new Stack<>();
Stack<Integer> depthst = new Stack<>();
int max = 0;
int depth = 1;
while (node !=null || nodest.size() > 0){
if (node!=null) {
nodest.push(node);
depthst.push(depth);
node = node.left;
depth++;
}else{
//当前结点为空,即该左树结束
node = nodest.pop();
depth = depthst.pop();
if(depth>max) max = depth;
// 遍历右子树
node = node.right;
depth++;
}
}
return max;
}
}

LeetCode 递归篇(70、22、98、104)的更多相关文章

  1. LeetCode刷题总结-递归篇

    递归是算法学习中很基本也很常用的一种方法,但是对于初学者来说比较难以理解(PS:难点在于不断调用自身,产生多个返回值,理不清其返回值的具体顺序,以及最终的返回值到底是哪一个?).因此,本文将选择Lee ...

  2. Recursive - leetcode [递归]

    经验tips: Recursion is the best friend of tree-related problems. 一是只要遇到字符串的子序列或配准问题首先考虑动态规划DP,二是只要遇到需要 ...

  3. [LeetCode]题解(python):104 Maximum Depth of Binary Tree

    题目来源 https://leetcode.com/problems/maximum-depth-of-binary-tree/ Given a binary tree, find its maxim ...

  4. LeetCode 递归(Recursion) 培训专题 讲解文章翻译 (附链接)

     递归 - 时间复杂度 在本文中, 我们主要介绍如何分析递归算法程序中的时间复杂度.. 在一个递归程序中, 它的时间复杂度 O(T) 一般来说就是他总共递归调用的次数 (定义为 R) 以及每次调用时所 ...

  5. LeetCode Weekly Contest 70 A B C D

    A. K-th Symbol in Grammar Description On the first row, we write a 0. Now in every subsequent row, w ...

  6. LeetCode || 递归 / 回溯

    呜呜呜 递归好不想写qwq 求“所有情况”这种就递归 17. Letter Combinations of a Phone Number 题意:在九宫格上按数字,输出所有可能的字母组合 Input: ...

  7. eetCode刷题-递归篇

    递归是算法学习中很基本也很常用的一种方法,但是对于初学者来说比较难以理解(PS:难点在于不断调用自身,产生多个返回值,理不清其返回值的具体顺序,以及最终的返回值到底是哪一个?).因此,本文将选择Lee ...

  8. leetcode刷题-95/96/98

    题目95题 给定一个整数 n,生成所有由 1 ... n 为节点所组成的 二叉搜索树 . 示例: 输入:3输出:[  [1,null,3,2],  [3,2,null,1],  [3,1,null,n ...

  9. LeetCode Javascript实现 258. Add Digits 104. Maximum Depth of Binary Tree 226. Invert Binary Tree

    258. Add Digits Digit root 数根问题 /** * @param {number} num * @return {number} */ var addDigits = func ...

  10. LeetCode递归解题模板

    39 40 78. Subsets https://leetcode.com/problems/subsets/description/ void subsets(vector<int>& ...

随机推荐

  1. QPixmap、QIcon和QImage

    QPixmap依赖于硬件,QImage不依赖于硬件.QPixmap主要是用于绘图,针对屏幕显示而最佳化设计,QImage主要是为图像I/O.图片访问和像素修改而设计的. 当图片小的情况下,直接用QPi ...

  2. java 处理常量字符串过长 & springboot 项目读取 resouces 文件夹下的文件内容

    长字符串起因 项目里面有一长串的加密字符串(最长的万多个字符),需要拼接作为参数发送给第三方. 如果我们使用 枚举 定义的话,idea 编译的时候就会出现编译报错 Error: java:常量字符串过 ...

  3. [Python急救站]密码判断

    用Python做一个密码判断,用户输入注册密码,需要6位以上,包含数字.大写字母.小写字母. import re a = re.compile('[a-z]') b = re.compile('[A- ...

  4. JUC并发编程学习笔记(十四)异步回调

    异步回调 Future设计的初衷:对将来的某个事件的结果进行建模 在Future类的子类中可以找到CompletableFuture,在介绍中可以看到这是为非异步的请求使用一些异步的方法来处理 点进具 ...

  5. kali Linux安装pyenv

    前言 pyenvpyenv 可让你轻松地在多个 Python 版本之间切换,是一个非常不错的python版本管理工具 安装步骤 安装依赖 apt-get install -y make build-e ...

  6. 2022.7.15 jiazhaopeng 讲课纪要

    前言 由于难度仍然过高,难度再次下调,这节课主要在水绿.这节课讲的是并查集,之所以是以绿题为主是因为上了绿之后的题有一大半都要结合别的东西,初中生不会,所以只能讲的简单一点. ORZ%%% jzp学长 ...

  7. HBuilderx 创建 、运行uniapp项目

    uni-app官网介绍的 通过 HBuilderX 可视化界面 跟着小颖来创建一个自己的小程序 创建小程序 依次点击HBuilderx 左上方的按钮:文件->新建->项目 然后打开该界面, ...

  8. ${pageContext.request.contextPath}的理解和用法

    在做房产管理系统的时候用到了<from>标签的这个用法,这就来解释一下 ${pageContext.request.contextPath} 是JSP取得绝对路径的方法,等价于 ${pag ...

  9. list.add()语句作用

    ----该方法用于向集合列表中添加对象 示例  本示例使用List接口的实现类ArrayList初始化一个列表对象,然后调用add方法向该列表中添加数据. public static void mai ...

  10. mysql数据库数据同步几种通用方法?

    MySQL数据库数据同步的几种通用方法包括以下几个方面: 一.基于主从同步 主从同步是 MySQL 数据库最为常见和基本的同步方式,即其中一台 MySQL 服务器作为主服务器(Master),另外一台 ...