【综合算法学习】(第十九篇)

目录

不同路径(medium)

题目解析

讲解算法原理

编写代码

最⻓递增⼦序列(medium)

题目解析

讲解算法原理

编写代码


不同路径(medium)

题目解析

1.题目链接:. - 力扣(LeetCode)

2.题目描述

⼀个机器⼈位于⼀个mxn⽹格的左上⻆(起始点在下图中标记为"Start")。机器⼈每次只能向下或者向右移动⼀步。机器⼈试图达到⽹格的右下⻆(在下图中标记为"Finish")。

问总共有多少条不同的路径?

⽰例1:

输⼊:m=3,n=7

输出:28

⽰例2:

输⼊:m=3,n=2

输出:3

解释:

从左上⻆开始,总共有3条路径可以到达右下⻆。

1.向右->向下->向下

2.向下->向下->向右

3.向下->向右->向下

讲解算法原理

解法(暴搜->记忆化搜索->动态规划):
算法思路:
暴搜:

a. 递归含义:给 dfs ⼀个使命,给他⼀个下标,返回从 0, 0 位置⾛到 i, j 位置⼀

共有多少种⽅法;

b. 函数体:只要知道到达上⾯位置的⽅法数以及到达左边位置的⽅法数,然后累加起来即可;c. 递归出⼝:当下标越界的时候返回 0 ;当位于起点的时候,返回 1 。

记忆化搜索:

a. 加上⼀个备忘录;

b. 每次进⼊递归的时候,去备忘录⾥⾯看看;

c. 每次返回的时候,将结果加⼊到备忘录⾥⾯。

动态规划:

a. 递归含义->状态表⽰;

b. 函数体->状态转移⽅程;

c. 递归出⼝->初始化。

编写代码

c++算法代码:

cpp 复制代码
class Solution
{
public:
 int uniquePaths(int m, int n) 
 {
 // 动态规划
 vector<vector<int>> dp(m + 1, vector<int>(n + 1));
 dp[1][1] = 1;
 for(int i = 1; i <= m; i++)
 for(int j = 1; j <= n; j++)
 {
 if(i == 1 && j == 1) continue;
 dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
 }
 return dp[m][n];
 // 记忆化搜索
 // vector<vector<int>> memo(m + 1, vector<int>(n + 1));
 // return dfs(m, n, memo);
 }
 int dfs(int i, int j, vector<vector<int>>& memo)
 {
 if(memo[i][j] != 0)
 {
 return memo[i][j];
 }
 if(i == 0 || j == 0) return 0;
 if(i == 1 && j == 1)
 {
 memo[i][j] = 1;
 return 1;
 }
 memo[i][j] = dfs(i - 1, j, memo) + dfs(i, j - 1, memo);
 return memo[i][j];
 }
};

java算法代码:

java 复制代码
class Solution
{
 public int uniquePaths(int m, int n) 
 {
 // 动态规划
 int[][] dp = new int[m + 1][n + 1];
 dp[1][1] = 1;
 for(int i = 1; i <= m; i++)
 for(int j = 1; j <= n; j++)
 {
 if(i == 1 && j == 1) continue;
 dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
 }
 return dp[m][n];
 // 记忆化搜索
 // int[][] memo = new int[m + 1][n + 1];
 // return dfs(m, n, memo);
 }
 public int dfs(int i, int j, int[][] memo)
 {
 if(memo[i][j] != 0)
 {
 return memo[i][j];
 }
 if(i == 0 || j == 0) return 0;
 if(i == 1 && j == 1) 
 {
 memo[i][j] = 1;
 return 1;
 }
 memo[i][j] = dfs(i - 1, j, memo) + dfs(i, j - 1, memo);
 return memo[i][j];
 }
}

最⻓递增⼦序列(medium)

题目解析

1.题目链接:. - 力扣(LeetCode)

2.题目描述

给你⼀个整数数组nums,找到其中最⻓严格递增⼦序列的⻓度。⼦序列是由数组派⽣⽽来的序列,删除(或不删除)数组中的元素⽽不改变其余元素的顺序。例

如,3,6,2,7是数组0,3,1,6,2,2,7的⼦序列。

⽰例1:

输⼊:nums=10,9,2,5,3,7,101,18

输出:4

解释:最⻓递增⼦序列是2,3,7,101,因此⻓度为4。

⽰例2:

输⼊:nums=0,1,0,3,2,3

输出:4

⽰例3:

输⼊:nums=7,7,7,7,7,7,7

输出:1

提⽰:

1<=nums.length<=2500

-10^4<=numsi<=10^4

讲解算法原理

解法(暴搜->记忆化搜索->动态规划):
算法思路:
暴搜:

a. 递归含义:给 dfs ⼀个使命,给他⼀个数 i ,返回以 i 位置为起点的最⻓递增⼦序列的⻓

度;

b. 函数体:遍历 i 后⾯的所有位置,看看谁能加到 i 这个元素的后⾯。统计所有情况下的最⼤

值。

c. 递归出⼝:因为我们是判断之后再进⼊递归的,因此没有出⼝~

记忆化搜索:

a. 加上⼀个备忘录;

b. 每次进⼊递归的时候,去备忘录⾥⾯看看;

c. 每次返回的时候,将结果加⼊到备忘录⾥⾯。

动态规划:

a. 递归含义->状态表⽰;

b. 函数体->状态转移⽅程;

c. 递归出⼝->初始化。

编写代码

c++算法代码:

cpp 复制代码
class Solution
{
public:
 int lengthOfLIS(vector<int>& nums) 
 {
 // 动态规划
 int n = nums.size();
 vector<int> dp(n, 1);
 int ret = 0;
 // 填表顺序:从后往前
 for(int i = n - 1; i >= 0; i--)
 {
 for(int j = i + 1; j < n; j++)
 {
 if(nums[j] > nums[i])
 {
 dp[i] = max(dp[i], dp[j] + 1);
 }
 }
 ret = max(ret, dp[i]);
 }
 return ret;
 
 // 记忆化搜索
 // 
 // vector<int> memo(n);
 // int ret = 0;
 // for(int i = 0; i < n; i++)
 // ret = max(ret, dfs(i, nums, memo));
 // return ret;
 }
 int dfs(int pos, vector<int>& nums, vector<int>& memo)
 {
 if(memo[pos] != 0) return memo[pos];
 int ret = 1;
 for(int i = pos + 1; i < nums.size(); i++)
 {
 if(nums[i] > nums[pos])
 {
 ret = max(ret, dfs(i, nums, memo) + 1);
 }
 }
 memo[pos] = ret;
 return ret;
 }
};

java算法代码:

java 复制代码
class Solution
{
 public int lengthOfLIS(int[] nums) 
 {
 int n = nums.length;
 int[] dp = new int[n];
 int ret = 0;
 Arrays.fill(dp, 1);
 // 填表顺序: 从后往前
 for(int i = n - 1; i >= 0; i--)
 {
 for(int j = i + 1; j < n; j++)
 {
 if(nums[j] > nums[i])
 {
 dp[i] = Math.max(dp[i], dp[j] + 1);
 }
 }
 ret = Math.max(ret, dp[i]);
 }
 return ret;
 
 // 记忆化搜索
 // int ret = 0;
 // int n = nums.length;
 // int[] memo = new int[n];
 // for(int i = 0; i < n; i++)
 // {
 // ret = Math.max(ret, dfs(i, nums, memo));
 // }
 // return ret;
 }
 public int dfs(int pos, int[] nums, int[] memo)
 {
 if(memo[pos] != 0) return memo[pos];
 int ret = 1;
 for(int i = pos + 1; i < nums.length; i++)
 {
 if(nums[i] > nums[pos])
 {
 ret = Math.max(ret, dfs(i, nums, memo) + 1);
 }
 }
 memo[pos] = ret;
 return ret;
 }
}
相关推荐
高冷小鱼殿下2 分钟前
C 语言指针与输入输出
c++
CC数分3 分钟前
统计学基础|先把问题问对:数据分析的六大类型
大数据·人工智能·算法
吹什么轩22 分钟前
constexpr 完全指南:从 const 的两种含义,到编译期计算的四次演进
java·前端·javascript
她的男孩33 分钟前
租户 A 的验证码,却用了租户 B 的 AccessKey:Forge Admin 修跨租户短信串发
java·spring boot·saas
LabVIEW开发35 分钟前
LabVIEW 局部变量与数据流:这道 CLAD 题为什么答案是 Undefined
java·开发语言·labview
文丑颜不良啊35 分钟前
LeetCode1721~1740题目解析
java·leetcode
地平线开发者37 分钟前
CLIP 的训练机制:从对比学习到图文对齐
深度学习·算法·自动驾驶
路溪非溪38 分钟前
C++标准库之智能指针
linux·开发语言·c++
wangbing112539 分钟前
监控网页项目常用英文缩写
java
麻瓜code44 分钟前
双写一致性:为什么是“删缓存“,而不是“改缓存“
java·缓存·mybatis