LeetCode 递归篇(70、22、98、104)
70. 爬楼梯
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
示例 1:
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
- 1 阶 + 1 阶
- 2 阶
示例 2:
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
- 1 阶 + 1 阶 + 1 阶
- 1 阶 + 2 阶
- 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)的更多相关文章
- LeetCode刷题总结-递归篇
递归是算法学习中很基本也很常用的一种方法,但是对于初学者来说比较难以理解(PS:难点在于不断调用自身,产生多个返回值,理不清其返回值的具体顺序,以及最终的返回值到底是哪一个?).因此,本文将选择Lee ...
- Recursive - leetcode [递归]
经验tips: Recursion is the best friend of tree-related problems. 一是只要遇到字符串的子序列或配准问题首先考虑动态规划DP,二是只要遇到需要 ...
- [LeetCode]题解(python):104 Maximum Depth of Binary Tree
题目来源 https://leetcode.com/problems/maximum-depth-of-binary-tree/ Given a binary tree, find its maxim ...
- LeetCode 递归(Recursion) 培训专题 讲解文章翻译 (附链接)
递归 - 时间复杂度 在本文中, 我们主要介绍如何分析递归算法程序中的时间复杂度.. 在一个递归程序中, 它的时间复杂度 O(T) 一般来说就是他总共递归调用的次数 (定义为 R) 以及每次调用时所 ...
- 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 ...
- LeetCode || 递归 / 回溯
呜呜呜 递归好不想写qwq 求“所有情况”这种就递归 17. Letter Combinations of a Phone Number 题意:在九宫格上按数字,输出所有可能的字母组合 Input: ...
- eetCode刷题-递归篇
递归是算法学习中很基本也很常用的一种方法,但是对于初学者来说比较难以理解(PS:难点在于不断调用自身,产生多个返回值,理不清其返回值的具体顺序,以及最终的返回值到底是哪一个?).因此,本文将选择Lee ...
- leetcode刷题-95/96/98
题目95题 给定一个整数 n,生成所有由 1 ... n 为节点所组成的 二叉搜索树 . 示例: 输入:3输出:[ [1,null,3,2], [3,2,null,1], [3,1,null,n ...
- 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 ...
- LeetCode递归解题模板
39 40 78. Subsets https://leetcode.com/problems/subsets/description/ void subsets(vector<int>& ...
随机推荐
- 文心一言 VS 讯飞星火 VS chatgpt (119)-- 算法导论10.3 4题
四.用go语言,我们往往希望双向链表的所有元素在存储器中保持紧凑,例如,在多数组表示中占用前m 个下标位置.(在页式虚拟存储的计算环境下,即为这种情况.)假设除指向链表本身的指针外没有其他指针指向该链 ...
- 虹科案例 | Redis企业版数据库帮助金融机构满足客户需求
如今,传统银行与新兴银行正在进行激烈的竞争.随着苹果.亚马逊.谷歌等科技巨头正凭借其数字化.移动应用程序和云体验打入金融服务行业.为了进行公平竞争,传统银行也需要通过个性化的全渠道客户体验来实现交互式 ...
- TOPSIS模型
TOPSIS模型主要是用于评估类模型 一些基本概念: 因为TOPSIS模型是用于评价类的模型,所以会有一些指标的概念,所有指标并非越大越好,例如我们在评价一人的时候会有成绩.和他人发生争吵的次数这两个 ...
- umich cv-6-1 循环神经网络基本知识
这节课中介绍了循环神经网络的第一部分,主要介绍了循环神经网络的基本概念,vanilla循环网络架构,RNN的一些应用,vanilla架构的问题,更先进的rnn架构比如GRU和LSTM 循环神经网络基本 ...
- DHorse改用fabric8的SDK与k8s集群交互
现状 在dhorse 1.4.0版本之前,一直使用k8s官方提供的sdk与k8s集群交互,官方sdk的Maven坐标如下: <dependency> <groupId>io.k ...
- App支付报错"商家订单参数异常,请重新发起付款"排查流程
今天在对接支付宝 APP 支付的时候遇到了一个报错,记录下问题的排查过程~ 报错过程 APP 中弹窗提示的报错"商家订单参数异常,请重新发起付款",检查了下参数感觉没啥问题,不知道 ...
- go语言写http踩得坑
1.在运行http时,报错:panic: listen tcp: address xxxx: missing port in address, 初始 代码如下 func HelloWordHander ...
- JVM Stack and Frame
Overview Sharing a single thread within the district: PC Register/JVM Stack/Native Method Stack.All ...
- 深入了解Rabbit加密技术:原理、实现与应用
一.引言 在信息时代,数据安全愈发受到重视,加密技术作为保障信息安全的核心手段,得到了广泛的研究与应用.Rabbit加密技术作为一种新型加密方法,具有较高的安全性和便捷性.本文将对Rabbit加密技术 ...
- 深入了解MD5加密技术及其应用与局限
一.MD5简介 MD5(Message Digest Algorithm 5)是一种单向散列函数,由美国密码学家罗纳德·李维斯特(Ronald Linn Rivest)于1991年发明.它主要用于将任 ...