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/ [题意] 给定一个字符串,求最少切割多少下,使得切割后的每个 ...
随机推荐
- 在线问诊 Python、FastAPI、Neo4j — 问题咨询
目录 查出节点 拼接节点属性 测试结果 问答演示 通过节点关系,找出对应的节点,获取节点属性值,并拼接成想要的结果. 接上节生成的CQL # 输入 question_class = {'args': ...
- ELK+ filebeat
ELK 企业级日志分析系统 ELK 概述 1.ELK 简介 ELK平台是一套完整的日志集中处理解决方案,将 ElasticSearch.Logstash 和 Kiabana 三个开源工具配合使用, 完 ...
- 使用 DDPO 在 TRL 中微调 Stable Diffusion 模型
引言 扩散模型 (如 DALL-E 2.Stable Diffusion) 是一类文生图模型,在生成图像 (尤其是有照片级真实感的图像) 方面取得了广泛成功.然而,这些模型生成的图像可能并不总是符合人 ...
- 《最新出炉》系列初窥篇-Python+Playwright自动化测试-22-处理select下拉框-上篇
1.简介 在实际自动化测试过程中,我们也避免不了会遇到下拉框选择的测试,因此宏哥在这里直接分享和介绍一下,希望小伙伴或者童鞋们在以后工作中遇到可以有所帮助.今天,我们讲下playwright的下拉框怎 ...
- 初识FreeRTOS
FreeRTOS是一个迷你的实时操作系统内核.作为一个轻量级的操作系统,功能包括:任务管理.时间管理.信号量.消息队列.内存管理.记录功能.软件定时器.协程等,可基本满足较小系统的需要. 一.Fr ...
- Web服务器及Web应用服务器
1. 如果仅需要展示html页面,而不要其他功能,apache:(nginx也是类似功能:它本身仅提供html静态页面的功能,不能支持jsp.java servlet.asp等功能,但通过同其他应用服 ...
- Kafka 集群如何实现数据同步?
哈喽大家好,我是咸鱼 最近这段时间比较忙,将近一周没更新文章,再不更新我那为数不多的粉丝量就要库库往下掉了 T﹏T 刚好最近在学 Kafka,于是决定写篇跟 Kafka 相关的文章(文中有不对的地方欢 ...
- 一款实用的.NET Core加密解密工具类库
前言 在我们日常开发工作中,为了数据安全问题对数据加密.解密是必不可少的.加密方式有很多种如常见的AES,RSA,MD5,SAH1,SAH256,DES等,这时候假如我们有一个封装的对应加密解密工具类 ...
- iOS性能优化之内存分析
成功之前我们要做应该做的事情,成功之后我们才可以做喜欢做的事情. 从苹果的开发者文档里可以看到内存分类如下所示,其中 Leaked memory和 Abandoned memory 都属于应该释放 ...
- 关于如何来测一款app的思考
最近工作当中需要整体测一遍app,需要全方面思考并且尽可能覆盖所有待测点,因为整理总结了这篇关于app测试的总体大纲 一.功能测试 1.1界面测试 1.1.1导航测试 ---是否易于导航.导航是否直观 ...