LeetCode DP篇(62、63、322、887)
62. 不同路径
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
问总共有多少条不同的路径?
例如,上图是一个7 x 3 的网格。有多少可能的路径?
示例 1:
输入: m = 3, n = 2
输出: 3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。
- 向右 -> 向右 -> 向下
- 向右 -> 向下 -> 向右
- 向下 -> 向右 -> 向右
示例 2:
输入: m = 7, n = 3
输出: 28
提示:
1 <= m, n <= 100
题目数据保证答案小于等于 2 * 10 ^ 9
solution1 动态规划
class Solution {
public int uniquePaths(int m, int n) {
int[] col = new int[n]; //用数组记录之前列的路径
Arrays.fill(col,1);
for (int i=1; i<m; i++){
for (int j=1; j<n; j++){
col[j] += col[j-1];//第一行永为1,每一个点路径数等于左边+上边(col[j] = col[j]+col[j-1])
}
}
return col[n-1];
}
}
class Solution {
public int uniquePaths(int m, int n) {
int[][] chart = new int[m][n];
for (int i=0; i<m; i++) chart[i][0] = 1;
for (int i=0; i<n; i++) chart[0][i] = 1;
for (int i=1; i<m; i++){
for (int j=1; j<n; j++){
chart[i][j] = chart[i-1][j] + chart[i][j-1];
}
}
return chart[m-1][n-1];
}
}
63. 不同路径 II
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。
现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?
网格中的障碍物和空位置分别用 1 和 0 来表示。
说明:m 和 n 的值均不超过 100。
示例 1:
输入:
[
[0,0,0],
[0,1,0],
[0,0,0]
]
输出: 2
解释:
3x3 网格的正中间有一个障碍物。
从左上角到右下角一共有 2 条不同的路径:
- 向右 -> 向右 -> 向下 -> 向下
- 向下 -> 向下 -> 向右 -> 向右
solution1 DP
class Solution {
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
int height = obstacleGrid.length;
int[] col = new int[height];
col[0] = 1;
for (int i=0; i<obstacleGrid[0].length; i++){
for (int j=0; j<obstacleGrid.length; j++){
if (obstacleGrid[j][i] == 1) col[j] = 0;
else if (j>0) col[j] += col[j-1];
}
}
return col[height-1];
}
}
class Solution {
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
int width = obstacleGrid[0].length;
int[] dp = new int[width];
dp[0] = 1;
for (int[] row : obstacleGrid){
for (int i=0; i<width; i++){
if (row[i] == 1) dp[i] = 0;
else if (i>0) dp[i] += dp[i-1];
}
}
return dp[width-1];
}
322. 零钱兑换
给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。
示例 1:
输入: coins = [1, 2, 5], amount = 11
输出: 3
解释: 11 = 5 + 5 + 1
示例 2:
输入: coins = [2], amount = 3
输出: -1
说明:
你可以认为每种硬币的数量是无限的。
solution1 暴力递归 (自顶向下)
class Solution {
public int coinChange(int[] coins, int amount) {
return helper(coins,amount);
}
public int helper(int[] coins, int n){
if(n == 0) return 0;
if(n < 0) return -1;
int res = n + 1;
for(int coin:coins){
int subres = helper(coins,n - coin); //状态转移方程
if(subres == -1) continue;
res = Math.min(res,subres+1);//最优子结构
}
return res >= n+1 ? -1:res;
}
}
solution2 带备忘录递归
class Solution {
public int coinChange(int[] coins, int amount) {
int[] count = new int[amount];
return helper(coins,amount,count);
}
public int helper(int[] coins, int n,int[] count){
if(n == 0) return 0;
if(n < 0) return -1;
if(count[n-1] != 0) return count[n-1];
int res = n + 1;
for(int coin:coins){
int subres = helper(coins,n - coin,count); //状态转移方程
if(subres == -1) continue;
res = Math.min(res,subres+1);//最优子结构
}
return count[n-1] = res >= n+1 ? -1:res;
}
}
solution3 动态规划 自底向上
class Solution {
public int coinChange(int[] coins, int amount) {
int max = amount + 1;
int[] dp = new int[amount+1];
Arrays.fill(dp,max);
dp[0] = 0;
for (int i = 1; i <= amount; i++){
for (int j = 0; j < coins.length; j++){
if(coins[j] <= i){
dp[i] = Math.min(dp[i],dp[i-coins[j]]+1); //状态转移方程
}
}
}
return dp[amount] > amount ? -1:dp[amount];
}
}
思路
// 参考博客:https://leetcode-cn.com/problems/coin-change/solution/dong-tai-gui-hua-tao-lu-xiang-jie-by-wei-lai-bu-ke/
# 初始化 base case
dp[0][0][...] = base
# 进行状态转移
for 状态1 in 状态1的所有取值:
for 状态2 in 状态2的所有取值:
for ...
dp[状态1][状态2][...] = 求最值(选择1,选择2...)
887. 鸡蛋掉落
你将获得 K 个鸡蛋,并可以使用一栋从 1 到 N 共有 N 层楼的建筑。
每个蛋的功能都是一样的,如果一个蛋碎了,你就不能再把它掉下去。
你知道存在楼层 F ,满足 0 <= F <= N 任何从高于 F 的楼层落下的鸡蛋都会碎,从 F 楼层或比它低的楼层落下的鸡蛋都不会破。
每次移动,你可以取一个鸡蛋(如果你有完整的鸡蛋)并把它从任一楼层 X 扔下(满足 1 <= X <= N)。
你的目标是确切地知道 F 的值是多少。
无论 F 的初始值如何,你确定 F 的值的最小移动次数是多少?
示例 1:
输入:K = 1, N = 2
输出:2
解释:
鸡蛋从 1 楼掉落。如果它碎了,我们肯定知道 F = 0 。
否则,鸡蛋从 2 楼掉落。如果它碎了,我们肯定知道 F = 1 。
如果它没碎,那么我们肯定知道 F = 2 。
因此,在最坏的情况下我们需要移动 2 次以确定 F 是多少。
示例 2:
输入:K = 2, N = 6
输出:3
示例 3:
输入:K = 3, N = 14
输出:4
提示:
1 <= K <= 100
1 <= N <= 10000
solution1 备忘录+递归
class Solution {
public int superEggDrop(int K, int N) {
int[][] menu = new int[K+1][N+1];
return helper(K,N,menu);
}
public int helper(int k, int n, int[][] menu){
//base case
if (k == 1) return n;
if (n == 0) return 0;
if (menu[k][n] != 0) return menu[k][n];
int res = Integer.MAX_VALUE;
for(int i = 1; i < n+1; i++){
//不碎,往上投还剩下n-i层 k不变
//碎了,往下投i-1,k-1
res = Math.min(res,Math.max(helper(k,n-i,menu),helper(k-1,i-1,menu))+1);
}
menu[k][n] = res;
return res;
}
}
//思路1:递归+备忘录
//1.dp数组,两个维度:还剩下几层 还剩多少鸡蛋(鸡蛋个数可以影响剩下投法,剩下层数影响鸡蛋怎么投)
//2.base case
//3.计算每一层投下后 碎和不碎两种情况下还要投的次数,取最小值
solution 2 二分查找优化
class Solution {
public int superEggDrop(int K, int N) {
return helper(K,N);
}
Map<Integer, Integer> memo = new HashMap();
public int helper(int k, int n){
//base case
if (k == 1) return n;
if (n == 0) return 0;
if (memo.containsKey(n*100+k)) return memo.get(100*n+k);
int res = Integer.MAX_VALUE;
//二分查找
int l = 1, r = n;
while (l <= r){
int mid = (l+r) >> 1;
int noBroken = helper(k,n-mid);
int broken = helper(k-1,mid-1);
if (broken > noBroken){
r = r - 1;
res = Math.min(res,broken + 1);
}else{
l = l + 1;
res = Math.min(res,noBroken+1);
}
}
memo.put(n*100+k,res);
return memo.get(n*100+k);
}
}
LeetCode DP篇(62、63、322、887)的更多相关文章
- <LeetCode OJ> 62. / 63. Unique Paths(I / II)
62. Unique Paths My Submissions Question Total Accepted: 75227 Total Submissions: 214539 Difficulty: ...
- Leetcode之动态规划(DP)专题-63. 不同路径 II(Unique Paths II)
Leetcode之动态规划(DP)专题-63. 不同路径 II(Unique Paths II) 初级题目:Leetcode之动态规划(DP)专题-62. 不同路径(Unique Paths) 一个机 ...
- LeetCode:零钱兑换【322】【DP】
LeetCode:零钱兑换[322][DP] 题目描述 给定不同面额的硬币 coins 和一个总金额 amount.编写一个函数来计算可以凑成总金额所需的最少的硬币个数.如果没有任何一种硬币组合能组成 ...
- 【leetcode】62.63 Unique Paths
62. Unique Paths A robot is located at the top-left corner of a m x n grid (marked 'Start' in the di ...
- leetcode@ [62/63] Unique Paths II
class Solution { public: int uniquePathsWithObstacles(vector<vector<int>>& obstacleG ...
- [leetcode DP]63. Unique Paths II
Follow up for "Unique Paths": Now consider if some obstacles are added to the grids. How m ...
- [leetcode DP]62.Unique Paths
判断一个物体从左上角到右下角有多少种走法 class Solution(object): def uniquePaths(self, m, n): flag = [[1 for j in range( ...
- [leetcode DP]64. Minimum Path Sum
一个m*n的表格,每个格子有一个非负数,求从左上到右下最短的路径值 和62,63两个值是同一个思路,建立dp表,记录每个位置到右下角的最短路径的值 class Solution(object): de ...
- 【leetcode dp】629. K Inverse Pairs Array
https://leetcode.com/problems/k-inverse-pairs-array/description/ [题意] 给定n和k,求正好有k个逆序对的长度为n的序列有多少个,0& ...
- 【leetcode dp】132. Palindrome Partitioning II
https://leetcode.com/problems/palindrome-partitioning-ii/description/ [题意] 给定一个字符串,求最少切割多少下,使得切割后的每个 ...
随机推荐
- CCF PTA编程培训师资认证
考试费用: 双会员500元,任意一方单会员750元,报名考试同时成为CCF专业会员850元,非会员1000元. P/T2补考费用:双会员200元,任意一方单会员300元,非会员400元. T1补考费用 ...
- 2023年SWPU NSS 秋季招新赛 (校外赛道)WP—Crypto
一.Caesar_base 题目信息 s = "HIJKLMNOPQRSTUVWXYZABCDEFGhijklmnopqrstuvwxyzabcdefg0123456789+/" ...
- python爬虫入门(1)-开发环境配置
所谓的爬虫,就是通过模拟点击浏览器发送网络请求,接收站点请求响应,获取互联网信息的一组自动化程序. 也就是,只要浏览器(客户端)能做的事情,爬虫都能够做. 现在的互联网大数据时代,给予我们的 ...
- CSP2021游记
题外话 中午十二点半到了考场.没到时间不让进,恰巧发现 lhm 在对面饭店于是去讨论了一下上午 J 组的题,复习了线段树板子( 等到进考场坐好的时候已经两点半了,看考号本来以为我们同机房三个同学会坐一 ...
- FPGA常用IP核
前言: 芯片行业中的IP,一般称为IP(Intellectual Property)核,是具有知识产权核的集成电路芯核的总称.说白了就是厂家实现的具有特定功能工具,然后我们可以直接调用,就相当于是函数 ...
- 解密Prompt系列19. LLM Agent之数据分析领域的应用:Data-Copilot & InsightPilot
在之前的 LLM Agent+DB 的章节我们已经谈论过如何使用大模型接入数据库并获取数据,这一章我们聊聊大模型代理在数据分析领域的应用.数据分析主要是指在获取数据之后的数据清洗,数据处理,数据建模, ...
- SpringBoot + 通义千问 + 自定义React组件,支持EventStream数据解析!
一.前言 大家好!我是sum墨,一个一线的底层码农,平时喜欢研究和思考一些技术相关的问题并整理成文,限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教. 最近ChatGPT非常受欢迎,尤其是在编 ...
- 通用串口modbus转PROFIBUS DP网关PM-160在汽车行业的应用案例
通用串口modbus转PROFIBUS DP网关PM-160在汽车行业的应用案例 摘要: PM-160 是泗博公司生产的,可以实现串口与 PROFIBUS DP 协议数据通信的网关.此案例讲述的是通过 ...
- 2019-2020 ICPC Southwestern European Regional Programming Contest (SWERC 2019-20) L题(SG+状压)
题意:给定一个N*N的表格,其上有三种类型的方格:坚实的地面.潮湿的区域和保护区.连通的湿区方格形成湿区,当两个正方形共用一条边时,它们被认为是连接的.每个湿区必须连接到网格的左右两侧,并且不包含超过 ...
- 怎么在Android项目中导入ffmpeg库?
1.前言 在这里我以导入静态库(.a)为例进行分析,动态库(.so)是类似的.在导入前,各位要先编译好ffmpeg库,需要注意的是在编译的时候要开启交叉编译,目标平台为Android,其他平台的库(w ...