代码随想录算法训练营|动态规划三十八天~四十三天

news2025/1/12 10:51:27

 动态规划五部曲:

1、确定dp数组以及下标的含义

2、确定递推公式

3、dp数组如何初始化

4、确定遍历顺序

5、举例推导dp数组

三十八天

斐波那契数

509. 斐波那契数 - 力扣(LeetCode)

public class Solution {
    public int MonotoneIncreasingDigits(int n) {
        string s = n.ToString();
        
        int size = s.Length;
        for(int i=s.Length-1;i>0;i--){
            if(s[i-1] > s[i]){
                size=i;
                s = s.Substring(0,i-1)+(char)(s[i-1]-1)+s.Substring(i);
            }
        }
        for(int i=size;i<s.Length;i++){
            s = s.Substring(0,i)+'9'+s.Substring(i+1);
        }
        return int.Parse(s);
    }
}

爬楼梯

70. 爬楼梯 - 力扣(LeetCode)

public class Solution {
    public int ClimbStairs(int n) {
        if(n==1){return n;}
        int[] result = new int[n+1];
        result[1] = 1;
        result[2] = 2;
        for(int i=3;i<=n;i++){
            result[i] = result[i-1]+result[i-2];
        }

        return result[n];
    }
}

使用最少花费爬楼梯

746. 使用最小花费爬楼梯 - 力扣(LeetCode)

public class Solution {
    public int MinCostClimbingStairs(int[] cost) {
        if(cost.Length == 1){return 0;}

        int[] result = new int[cost.Length+1];
        result[0] = 0;
        result[1] = 0;
        for(int i=2;i<=cost.Length;i++){
            result[i] = Math.Min(result[i-1]+cost[i-1],result[i-2]+cost[i-2]);
        }
        return result[cost.Length];
    }
}

三十九天

不同路径

62. 不同路径 - 力扣(LeetCode)

按照五部曲,dp数组含义是从起点到[i,j]的路径总共有result[i,j]条路径;递归就是在点[0,0]到[1,1]有两条路,即[0,1]和[1,0],所以result[i,j]=result[i-1,j]+result[i,j-1];初始化就把纵横赋值为1,因为只有一个方法走,

public class Solution {
    public int UniquePaths(int m, int n) {
        int[,] result = new int[n,m];
        
        for(int i=0;i<n;i++){result[i,0] = 1;}
        for(int j=0;j<m;j++){result[0,j] = 1;}

        for(int i=1;i<n;i++){
            for(int j=1;j<m;j++){
                result[i,j] = result[i-1,j] + result[i,j-1];
            }
        }

        return result[n-1,m-1];
    }
}

不同路径||

63. 不同路径 II - 力扣(LeetCode)

和上一题比就多了个障碍,只要把障碍的位置记录就行了。

public class Solution {
    public int UniquePathsWithObstacles(int[][] obstacleGrid) {
        int n = obstacleGrid.Length;
        int m = obstacleGrid[0].Length;
        int[,] result = new int[n,m];

        if(obstacleGrid[n-1][m-1] == 1 || obstacleGrid[0][0] == 1){return 0;}

        for(int i=0;i<n && obstacleGrid[i][0] == 0;i++){
            result[i,0] = 1;
        }
        for(int i=0;i<m && obstacleGrid[0][i] == 0;i++){
            result[0,i] = 1;
        }

        for(int i=1;i<n;i++){
            for(int j=1;j<m;j++){
                if(obstacleGrid[i][j] != 1){
                    result[i,j] = result[i-1,j]+result[i,j-1];
                }
            }
        }

        return result[n-1,m-1];
    }
}

四十天

整数拆分

343. 整数拆分 - 力扣(LeetCode)

要点:这题递推比较难,有两个拆分方向,一个是j*(i-j),一个是j*result[i-j]。例如输入5,拆分1,4,然后4可以继续拆分成1,3,然后就取1*4和1*1*3的最大值,再赋值到result[i]

public class Solution {
    public int IntegerBreak(int n) {
        int[] result = new int[n+1];
        result[2] = 1;

        for(int i=3;i<=n;i++){
            for(int j=1;j<i-1;j++){
                result[i] = Math.Max(result[i],Math.Max(j*(i-j),j*result[i-j]));
            }
        }

        return result[n];
    }
}

不同的二叉搜索树

96. 不同的二叉搜索树 - 力扣(LeetCode)

要点:首先就是二叉树的左边比头结点小,右边比头结点大,其次,根据例题输入n=3,图,以及二叉树的特性,能推断出result[3] = result[2]*result[0] + result[1]*result[1] + result[0]*result[2],就是左子树元素节点数量*右子树元素节点数量。

关于result[0]=1:

从定义上来讲,空节点也是一棵二叉树,也是一棵二叉搜索树,这是可以说得通的。

从递归公式上来讲,dp[以j为头结点左子树节点数量] * dp[以j为头结点右子树节点数量] 中以j为头结点左子树节点数量为0,也需要dp[以j为头结点左子树节点数量] = 1, 否则乘法的结果就都变成0了。

public class Solution {
    public int NumTrees(int n) {
        int[] result = new int[n+1];
        result[0] = 1;

        for(int i=1;i<=n;i++){
            for(int j=1;j<=i;j++){
                result[i] += result[j-1]*result[i-j];
            }
        } 

        return  result[n];
    }
}

四十一天

背包问题

二维dp数组01背包:(详细看代码随想录 (programmercarl.com))

1、dp[i][j] 表示从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少。

2、递推公式:dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i])

不放物品i:dp[i - 1][j](由dp[i - 1][j]推出,即背包容量为j,里面不放物品i的最大价值,此时dp[i][j]就是dp[i - 1][j]。(其实就是当物品i的重量大于背包j的重量时,物品i无法放进背包中,所以背包内的价值依然和前面相同);

放物品:dp[i - 1][j - weight[i]] + value[i](由dp[i - 1][j - weight[i]]推出,dp[i - 1][j - weight[i]] 为背包容量为j - weight[i]的时候不放物品i的最大价值,那么dp[i - 1][j - weight[i]] + value[i] (物品i的价值),就是背包放物品i得到的最大价值)。

3、初始化

从dp[0][0]开始,纵向初始化为0,横向i>0,都初始化为物品0能放进背包时的价值,放不进也初始化为0;其他的也都可以初始化为0。

4、遍历顺序:

先遍历物品或者背包都可以。

先遍历物品

// weight数组的大小 就是物品个数
for(int i = 1; i < weight.size(); i++) { // 遍历物品
    for(int j = 0; j <= bagweight; j++) { // 遍历背包容量
        if (j < weight[i]) dp[i][j] = dp[i - 1][j];
        else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);

    }
}

一维数组(滚动数组,就是每次循环都覆盖在原来的数组中,二维数组是i*j的数组,一维数组只需要j)

1、dp[j]表示容量为j的背包,所背的物品价值可以最大为dp[j]。

2、递推公式:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

3、初始化:全部初始为0.

4、遍历顺序

for(int i = 0; i < weight.size(); i++) { // 遍历物品
    for(int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量
        dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

    }
}

 分割等和字集

416. 分割等和子集 - 力扣(LeetCode)

要点:这题是前面背包问题的应用,然后一维数组的递推公式在这里的平替是背包体积是target,重量和价值是nums。不过我还没完全懂,先挂在这后面慢慢想。

public class Solution {
    public bool CanPartition(int[] nums) {
        bool[] dp = new bool[10000];

        int sum = nums.Sum();
        if(sum % 2 == 1){return false;}
        int target = sum / 2;

        dp[0] =true;
        for(int i=0;i<nums.Length;i++){
            for(int j=target;j>=nums[i];j--){
                dp[j] = dp[j] || dp[j-nums[i]];
            }
        }
        return dp[target];
    }
}

四十二天

最后一块石头的重量||

1049. 最后一块石头的重量 II - 力扣(LeetCode)

和分割等和子集同样的思路

public class Solution {
    public int LastStoneWeightII(int[] stones) {
        int sum = stones.Sum();
        int target = sum/2;
        int[] dp = new int[target+1];

        for(int i=0;i<stones.Length;i++){
            for(int j=target;j>=stones[i];j--){
                dp[j] = Math.Max(dp[j],dp[j-stones[i]]+stones[i]);
            }
        }
        return sum - 2*dp[target];  
    }
}

目标和

494. 目标和 - 力扣(LeetCode)

public class Solution {
    public int FindTargetSumWays(int[] nums, int target) {
        int sum = nums.Sum();
        if(Math.Abs(target) > sum){return 0;}
        if((target+sum)%2 == 1){return 0;}
        int bagLength = (target+sum) / 2;
        int[] dp = new int[bagLength+1];
        dp[0] = 1;
        for(int i=0;i<nums.Length;i++){
            for(int j=bagLength;j>=nums[i];j--){
                dp[j] += dp[j-nums[i]];
            }
        }
        return dp[bagLength];
    }
}

一和零

474. 一和零 - 力扣(LeetCode)

public class Solution {
    public int FindMaxForm(string[] strs, int m, int n) {
        int[,] dp= new int[m+1,n+1];
        foreach(string s in strs){
            int zeroNum = 0;
            int oneNum = 0;
            foreach(char a in s){
                if(a == '0')zeroNum++;
                else oneNum++;
            }
            for(int i=m;i>=zeroNum;i--){
                for(int j=n;j>=oneNum;j--){
                    dp[i,j] = Math.Max(dp[i,j],dp[i-zeroNum,j-oneNum]+1);
                }
            }
        }

        return dp[m,n];
    }
}

目前,我对所有的01背包问题都不懂!

四十三天

完全背包:所有物品都能无限放入背包

零钱兑换||

518. 零钱兑换 II - 力扣(LeetCode)

看起来和那个目标和的题差不多,对物品的使用次数没限制。不过还是不太懂。

public class Solution {
    public int Change(int amount, int[] coins) {
        int[] dp = new int[amount+1];
        dp[0] = 1;
        for(int i=0;i<coins.Length;i++){
            for(int j = coins[i];j<=amount;j++){
                dp[j] += dp[j-coins[i]];
            }
        }

        return dp[amount];
    }
}

组合总和IV

377. 组合总和 Ⅳ - 力扣(LeetCode)

public class Solution {
    public int CombinationSum4(int[] nums, int target) {
        int[] dp = new int[target + 1];
        dp[0] = 1;
        for (int i = 0; i <= target; i++) {
            for (int j = 0; j < nums.Length; j++) {
                if (i - nums[j] >= 0 && dp[i] < int.MaxValue - dp[i - nums[j]]) {
                    dp[i] += dp[i - nums[j]];
                }
            }
        }
        return dp[target];
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1198480.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

训练日志刷屏使我痛苦,我开发了VLog

训练日志刷屏使我痛苦&#xff0c;我开发了VLog&#xff0c;可以在任意训练代码中轻松使用~ 例如&#xff0c;通过callback嵌入到lightgbm/catboost/transformers/ultralytics&#xff0c;乃至keras库的训练代码流程中~ before: after&#xff1a; 为什么不用tensorboard或者wa…

Linux的make和Makefile

目录 一、 介绍二、快速使用三、依赖关系和依赖方法四、语法 一、 介绍 1、makefile带来的好处就是——“自动化编译”&#xff0c;一旦写好&#xff0c;只需要一个make命令&#xff0c;整个工程完全自动编译&#xff0c;极大的提高了软件开发的效率。 2、make是一个命令工具&…

dcat admin 各种问题

样式问题 如何根据条件给表格数据栏添加背景色 use Illuminate\Support\Collection;protected function grid(){return Grid::make(new BookArticle(), function (Grid $grid) {... 其他代码// Collection的完整路径&#xff1a;Illuminate\Support\Collection;$grid->row…

火星加载WMTS服务

这是正常的加载瓦片 http://192.168.1.23:8008/geoserver/mars3d/gwc/service/wmts?tilematrixEPSG%3A4326%3A7&layermars3d%3Abuffer&style&tilerow46&tilecol197&tilematrixsetEPSG%3A4326&formatimage%2Fpng&serviceWMTS&version1.0.0&…

超详细介绍对极几何和立体视觉及 Python 和 C++实现

您是否想过为什么戴着特殊的 3D 眼镜观看电影时可以体验到美妙的 3D 效果?或者为什么闭上一只眼睛很难接住板球?这一切都与立体视觉有关,立体视觉是我们用双眼感知深度的能力。这篇文章使用 OpenCV 和立体视觉为计算机提供这种感知深度的能力。代码以 Python 和 C++ 形式提供…

迷雾系统-1 地图及其区块

创建UGUI地图,每块地块&#xff08;Image&#xff09;上添加AreaNode脚本&#xff0c;根据PolygonCollider2D可视化编辑碰撞体形状&#xff0c;并以此生成Mesh Mc_AreaNode脚本&#xff1a; private GameObject _objPrefab; //创建的Mesh预制体private float _canvasPosZ;pr…

[N-133]基于springboot,vue小说网站

开发工具&#xff1a;IDEA 服务器&#xff1a;Tomcat9.0&#xff0c; jdk1.8 项目构建&#xff1a;maven 数据库&#xff1a;mysql5.7 系统分前后台&#xff0c;项目采用前后端分离 前端技术&#xff1a;vueelementUI 服务端技术&#xff1a;springbootmybatis-plus 本项…

【Java面向对象编程(中)】- 探索封装的秘密

&#x1f308;个人主页: Aileen_0v0&#x1f525;系列专栏:Java学习系列专栏&#x1f4ab;个人格言:"没有罗马,那就自己创造罗马~" 目录 回顾 封装​编辑 为什么进行封装 ​​编辑​ 如何调用私有的变量 ​​编辑​ 1.get set方法(当形参和成员变量不同名时)​…

LeetCode | 138. 随机链表的复制

LeetCode | 138. 随机链表的复制 OJ链接 思路&#xff1a; 题目要求我们拷贝一个带next指针与random随机访问指针的链表。 如果只拷贝一个只带next的指针&#xff0c;直接遍历目标链表依次拷贝每个节点的信息就可以了~~ 拷贝节点插入到原节点的后面处理copy节点的randomcop…

Leetcode—103.二叉树的锯齿形层序遍历【中等】

2023每日刷题&#xff08;二十六&#xff09; Leetcode—103.二叉树的锯齿形层序遍历 BFS实现代码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/ /*** Return an array of ar…

138.随机链表的复制(LeetCode)

深拷贝&#xff0c;是指将该链表除了正常单链表的数值和next指针拷贝&#xff0c;再将random指针进行拷贝 想法一 先拷贝出一份链表&#xff0c;再对于每个节点的random指针&#xff0c;在原链表进行遍历&#xff0c;找到random指针的指向&#xff0c;最后完成拷贝链表random…

第一百六十八回 NavigationBar组件

文章目录 1. 概念介绍2. 使用方法3. 代码与效果3.1 示例代码3.2 运行效果 4. 内容总结 我们在上一章回中介绍了"如何修改按钮的形状"相关的内容&#xff0c;本章回中将 介绍NavigationBar组件.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在本…

Linux驱动开发——PCI设备驱动

目录 一、 PCI协议简介 二、PCI和PCI-e 三、Linux PCI驱动 四、 PCI设备驱动实例 五、 总线类设备驱动开发习题 一、 PCI协议简介 PCI (Peripheral Component Interconnect&#xff0c;外设部件互联) 局部总线是由Intel 公司联合其他几家公司一起开发的一种总线标准&#…

初识-Servlet (第一个 Servlet 程序详解)

Servlet 是什么? Servlet 是一种实现动态页面的技术. 是一组 Tomcat 提供给程序员的 API, 帮助程序员简单高效的开发一个 web app. 静态页面就只是单纯的 html 动态页面则是 html 数据 第一个 Servlet 程序 我们写一个 hello world 预期写一个 Servlet 程序, 部署到 Tomca…

图论12-无向带权图及实现

文章目录 带权图1.1带权图的实现1.2 完整代码 带权图 1.1带权图的实现 在无向无权图的基础上&#xff0c;增加边的权。 使用TreeMap存储边的权重。 遍历输入文件&#xff0c;创建TreeMap adj存储每个节点。每个输入的adj节点链接新的TreeMap&#xff0c;存储相邻的边和权重 …

时间序列预测实战(十二)DLinear模型实现滚动长期预测并可视化预测结果

官方论文地址->官方论文地址 官方代码地址->官方代码地址 个人修改代码->个人修改的代码已经上传CSDN免费下载 一、本文介绍 本文给大家带来是DLinear模型&#xff0c;DLinear是一种用于时间序列预测&#xff08;TSF&#xff09;的简单架构&#xff0c;DLinear的核…

Leetcode刷题详解—— 目标和

1. 题目链接&#xff1a;494. 目标和 2. 题目描述&#xff1a; 给你一个非负整数数组 nums 和一个整数 target 。 向数组中的每个整数前添加 或 - &#xff0c;然后串联起所有整数&#xff0c;可以构造一个 表达式 &#xff1a; 例如&#xff0c;nums [2, 1] &#xff0c;可…

【计算机网络笔记】IP分片

系列文章目录 什么是计算机网络&#xff1f; 什么是网络协议&#xff1f; 计算机网络的结构 数据交换之电路交换 数据交换之报文交换和分组交换 分组交换 vs 电路交换 计算机网络性能&#xff08;1&#xff09;——速率、带宽、延迟 计算机网络性能&#xff08;2&#xff09;…

有没有实时检测微信聊天图片的软件,只要微信收到了有二维码的图片就把它提取出来?

10-2 如果你有需要自动并且快速地把微信收到的二维码图片保存到指定文件夹的需求&#xff0c;那本文章非常适合你&#xff0c;本文章教你如何实现自动保存微信收到的二维码图片到你指定的文件夹中&#xff0c;助你快速扫码&#xff0c;比别人领先一步。 首先需要准备好的材料…

19 异步通知

一、异步通知 1. 异步通知简介 阻塞和非阻塞两种方式都是需要应用程序去主动查询设备的使用情况。 异步通知类似于驱动可以主动报告自己可以访问&#xff0c;应用程序获取信号后会从驱动设备中读取或写入数据。 异步通知最核心的就是信号&#xff1a; #define SIGHUP 1 /* 终…