4.10 动态规划简单题

This commit is contained in:
zhangsan 2025-04-10 15:53:54 +08:00
parent 60c5f6969f
commit 515479d66e
5 changed files with 198 additions and 0 deletions

View File

@ -0,0 +1,28 @@
package dynamic_programming;
/**
* 题目 70. 爬楼梯 (climbStairs)
* 描述假设你正在爬楼梯需要 n 阶你才能到达楼顶
* 每次你可以爬 1 2 个台阶你有多少种不同的方法可以爬到楼顶呢
示例 2
输入n = 2
输出2
解释有两种方法可以爬到楼顶
1. 1 + 1
2. 2
* 链接https://leetcode.cn/problems/climbing-stairs/
*/
public class ClimbStairs {
public int climbStairs(int n) {
if(n <= 2) return n;
int a = 1, b = 2, sum = 0;
for(int i = 3; i <= n; i++){
sum = a + b; // f(i - 1) + f(i - 2)
a = b; // 记录f(i - 1)即下一轮的f(i - 2)
b = sum; // 记录f(i)即下一轮的f(i - 1)
}
return b;
}
}

View File

@ -0,0 +1,50 @@
package dynamic_programming;
import java.util.ArrayList;
import java.util.List;
/**
* 题目 118. 杨辉三角 (generate)
* 描述给定一个非负整数 numRows生成杨辉三角的前 numRows
*
* 杨辉三角每个数是它左上方和右上方的数的和
示例 2
输入: numRows = 5
输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]
* 链接https://leetcode.cn/problems/pascals-triangle/
*/
public class Generate {
public List<List<Integer>> generate(int numRows) {
List<List<Integer>>res=new ArrayList<>();
List<Integer>pre = null;
for (int i = 0; i < numRows; i++) {
List<Integer>temp=new ArrayList<>();
for (int j = 0; j < i+1; j++) {
if(j==0||j==i)
temp.add(1);
else temp.add(pre.get(j-1)+pre.get(j));
}
res.add(temp);
pre=new ArrayList<>(temp);
}
return res;
}
//官方题解 差不多
public List<List<Integer>> generate1(int numRows) {
List<List<Integer>> ret = new ArrayList<List<Integer>>();
for (int i = 0; i < numRows; ++i) {
List<Integer> row = new ArrayList<Integer>();
for (int j = 0; j <= i; ++j) {
if (j == 0 || j == i) {
row.add(1);
} else {
row.add(ret.get(i - 1).get(j - 1) + ret.get(i - 1).get(j));
}
}
ret.add(row);
}
return ret;
}
}

View File

@ -0,0 +1,37 @@
package dynamic_programming;
/**
* 题目 746. 使用最小花费爬楼梯 (MinCostClimbingStairs)
* 描述给你一个整数数组 cost 其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用一旦你支付此费用即可选择向上爬一个或者两个台阶
* 你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯
* 请你计算并返回达到楼梯顶部的最低花费
示例 2
输入cost = [10,15,20]
输出15
解释你将从下标为 1 的台阶开始
- 支付 15 向上爬两个台阶到达楼梯顶部
总花费为 15
* 链接https://leetcode.cn/problems/min-cost-climbing-stairs/
*/
public class MinCostClimbingStairs {
public int minCostClimbingStairs(int[] cost) {
int n = cost.length;
int[] dp = new int[n + 1];
// 默认第一步和第二步不花费体力
dp[0] = 0;
dp[1] = 0;
// 从第 2 阶开始递推计算到顶楼
for (int i = 2; i <= n; i++) {
dp[i] = Math.min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);
}
return dp[n];
}
// 供测试使用的main方法
public static void main(String[] args) {
MinCostClimbingStairs sol = new MinCostClimbingStairs();
int[] cost = {10, 15, 20};
System.out.println("最低花费为: " + sol.minCostClimbingStairs(cost));
}
}

View File

@ -0,0 +1,37 @@
package dynamic_programming;
/**
* 题目 62. 不同路径 (uniquePaths)
* 描述一个机器人位于一个 m x n 网格的左上角 起始点在下图中标记为 Start
* 机器人每次只能向下或者向右移动一步机器人试图达到网格的右下角在下图中标记为 Finish
* 问总共有多少条不同的路径
示例 2
输入m = 3, n = 2
输出3
解释
从左上角开始总共有 3 条路径可以到达右下角
1. 向右 -> 向下 -> 向下
2. 向下 -> 向下 -> 向右
3. 向下 -> 向右 -> 向下
* 链接https://leetcode.cn/problems/unique-paths/
*/
public class UniquePaths {
public static int uniquePaths(int m, int n) {
int[][] dp = new int[m][n];
//初始化
for (int i = 0; i < m; i++) { //首先dp[i][0]一定都是1因为从(0, 0)的位置到(i, 0)的路径只有一条那么dp[0][j]也同理
dp[i][0] = 1;
}
for (int i = 0; i < n; i++) {
dp[0][i] = 1;
}
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
dp[i][j] = dp[i-1][j]+dp[i][j-1];
}
}
return dp[m-1][n-1];
}
}

View File

@ -0,0 +1,46 @@
package dynamic_programming;
/**
* 题目 63. 不同路径 II (uniquePathsWithObstacles)
* 描述给定一个 m x n 的整数数组 grid一个机器人初始位于 左上角 grid[0][0]机器人尝试移动到 右下角 grid[m - 1][n - 1]机器人每次只能向下或者向右移动一步
* 网格中的障碍物和空位置分别用 1 0 来表示机器人的移动路径中不能包含 任何 有障碍物的方格
* 返回机器人能够到达右下角的不同路径数量
* 测试用例保证答案小于等于 2 * 109
示例 2
输入obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]]
输出2
解释3x3 网格的正中间有一个障碍物
从左上角到右下角一共有 2 条不同的路径
1. 向右 -> 向右 -> 向下 -> 向下
2. 向下 -> 向下 -> 向右 -> 向右
* 链接https://leetcode.cn/problems/unique-paths/
*/
public class UniquePathsWithObstacles {
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
int m=obstacleGrid.length,n=obstacleGrid[0].length;
int[][]dp=new int[m][n];
for (int i = 0; i < m; i++) { //首先dp[i][0]一定都是1因为从(0, 0)的位置到(i, 0)的路径只有一条那么dp[0][j]也同理
if(obstacleGrid[i][0]!=1)
dp[i][0] = 1;
else
break;
}
for (int i = 0; i < n; i++) {
if(obstacleGrid[0][i]!=1)
dp[0][i] = 1;
else
break;
}
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
if(obstacleGrid[i][j]==1)
dp[i][j]=0;
else
dp[i][j] = dp[i-1][j]+dp[i][j-1];
}
}
return dp[m-1][n-1];
}
}