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. PPT图片处理教程5大抠图方法:堪比PS!

    PPT图片处理教程5大抠图方法:堪比PS! .如何在制作PPT的过程中提取图片.比如,当你准备给妹子做一份PPT的时候,妹子想要把N多图片放在里面,但又不想做的太LOW,这要怎么解(gai)咯?如果你 ...

  2. Arduino Uno 引脚 –

    Arduino Uno 引脚 – Arduino Uno 板有 20 多个引脚,可用于许多不同的应用.在这篇文章中,我将为您提供 Arduino Uno 主要引脚的完整实用概述. 如果您刚开始使用 A ...

  3. 教育法学第六章单元测试MOOC

    第六章单元测试 返回 本次得分为:100.00/100.00, 本次测试的提交时间为:2020-09-06, 如果你认为本次测试成绩不理想,你可以选择 再做一次 . 1 单选(5分) "学习 ...

  4. Semantic Kernel .NET SDK 的 v1.0.0 Beta1 发布

    介绍 Semantic Kernel (SK) 是一个开源的将大型语言模型(LLM)与流行的编程语言相结合的SDK,Microsoft将Semantic Kernel(简称SK)称为轻量级SDK,结合 ...

  5. 基于SpringBoot+Netty实现即时通讯(IM)功能

    简单记录一下实现的整体框架,具体细节在实际生产中再细化就可以了. 第一步 引入netty依赖 SpringBoot的其他必要的依赖像Mybatis.Lombok这些都是老生常谈了 就不在这里放了 &l ...

  6. Vue之自定义过滤器

    使用Vue.filter('过滤器名称',方法); 1. <!DOCTYPE html> <html lang="en"> <head> < ...

  7. nodejs修改npm包安装位置

    适用于非个人电脑.便携使用 npm config set cache D:\nodejs\node_cache npm config set prefix D:\nodejs npm config s ...

  8. JavaScript(ES6):变量的解构赋值

    解构赋值定义: 允许按照一定模式从数组或对象中提取值,然后对变量进行赋值. 数组的解构赋值 注:数组的元素要一次排序的,变量的值由他的位置决定. 基本用法 // ES6 解构赋值 let [a, b, ...

  9. AJAX入门实例

    1.什么是 AJAX ? AJAX = 异步 JavaScript 和 XML. AJAX 是一种用于创建快速动态网页的技术. 通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新.这 ...

  10. 数据结构与算法 | 动态规划算法(Dynamic Programming)

    上一篇文末已经提到了记忆化搜索是动态规划(Dynamic Programming)的一种形式,是一种自顶向下(Top-Down)的思考方式,通常采用递归的编码形式:既然动态规划有自顶向下(Top-Do ...