dp算法篇Day1

news2024/11/26 0:39:43

 "多希望有人来陪我,度过末日啊~"


        讲讲我为什么突然想更新这篇栏目。

        想想自己也算 "系统" 接触计算机这个学科也有差不多一年了,回想起当初下定决心要全身心投入到这个专业或者说行业中来,现在到了这样的地步,是否很符合当初对自己的期待,对这个专业行业的期待?想想做软件开发相关最最基础的四大组件,算法和数据结构、操作系统和计算机网络、数据库,再怎么说到了现在也涉略一二。对于我来说,除了在系统部分上很花时间外,其次就应当属算法,当然很多算法也会相关到部分容器,那么这类题目也会变成算法+数据结构的”双重打击”。

        在第一次接触算法的时候,给我的感觉就是需要投入的时间大,以及微乎可微的反馈成果。所以一开始我对于算法其实是持有排斥的状态。可是,当你看到各个公司的笔试题,首当其冲给你甩几道面试题,而你却迟迟敲不了几行代码、捶胸敦促……痛定思痛之后,不得不重视到代码能力的提升上,其中唯一一条且至关重要的,且是一个从业者也会建议的—— “多刷刷算法题“。

        道理我都懂,我也有时间有那个心气去刷,可是看到那一个个标榜“简单”难度的迟迟做不出来,一看题解似乎并没有想象的那么难,有那么点道理,开始理解,而此时评论区一片 “简单的、祥和”的画面。到一个标榜“中等”难度的题似乎成了更难以跨越的"鸿沟"更别提 那写满一张网页的“题解”……

        你开始暗下决心,告诉自己“慢慢来”,你便”胸有成竹”般地给自己定下每天刷个3~4道算法题的小目标,于是乎你每天开始登上账号开始刷题,看着不会,翻翻题解,试着敲敲,似乎理解,运行成功,下一道题……而这种状态持续不了多久,你就会没了兴趣,因为你发现坚持了几天后,仍然是一事无成,竟没做出一道题!未免心里有些波动,有时候看到算法题就显得有些恐惧和排斥,那心里上暗示的每天刷题的目标,不自觉地变暗了下去,就连自己也不想再去记起……

        " 多希望有人来陪我,度过末日啊~"。

        还是那句话,永远不要放弃你自己,都是这么走过来的。


        永恒的题解思路:

 


1、第N个斐波那契数

 (1) 题意分析 

        本题肯定是非常简单的一种dp规划,因为题中就已经告知了dp的状态转移方程和初始化,没什么很大的难度。

class Solution {
public:
    int tribonacci(int n) {
        if(n < 1) return  0;
        if(n < 2 || n < 3) return 1;

        vector<int> dp(n+1);
        dp[0] = 0,dp[1] = dp[2]= 1;
        // 但是从T4 填dp表
        for(int i=3; i <= n; ++i)
            dp[i] = dp[i-1]+dp[i-2]+dp[i-3];
        
        return dp[n];
    }
};

 (2) 空间优化

        多数时候对dp的优化要求不是那么显眼,最主要的是做出来。我们分析上述代码的时空复杂度分别为,O(n) \ O(n)。

        在本题可以使用滚动数组,对空间复杂度进行优化,下降至O(1)的常数。

        因为要求 第n个泰波那契数,本质只需要知道它前三个数的状态即可~

class Solution {
public:
    int tribonacci(int n) {
        if(n < 1) return  0;
        if(n < 2 || n < 3) return 1;

        int a=0;
        int b=1,c=1;
        int d=0;
        // 这里从i下标3开始
        for(int i=3; i<=n; ++i){
            d = a + b + c;
            // 条件更新
            a = b;
            b = c;
            c = d;
        }
   
        return d;
    }
};

 


 

2、三步问题

(1) 题目解析 

         这道题桶上面那到泰波那契数,换汤不换药,仍然是根据题目得到状态表示,再根据状态表示相邻的位置,推出状态方程。 

边界位置:

class Solution {
public:
    int waysToStep(int n) {
        if(n == 1 || n==2) return n; 
        if(n == 3) return 4;
        
        // 题目要求 别忘记对加法mod
        const int MOD = 1e9+7;

        vector<int> dp(n+1);
        dp[1] = 1,dp[2]=2,dp[3]=4;

        for(int i=4; i<=n ;++i)
            dp[i] = ((dp[i-1] + dp[i-2]) % MOD + dp[i-3] ) % MOD;
        
        return dp[n];
    }
};

     


3、最小花费爬楼梯

(1) 题目解析

思路一: 到达i位置的最小花费

边界位置:

class Solution {
public:
    int minCostClimbingStairs(vector<int>& cost) {
        int n = cost.size();
        vector<int> dp(n+1);
        dp[0]=dp[1]=0;

        for(int i=2; i<=n; ++i)
            dp[i] = min(dp[i-1]+cost[i-1],dp[i-2]+cost[i-2]);

        return dp[n];
    }
};

思路二: 从i位置开始 的最小花费

class Solution {
public:
    int minCostClimbingStairs(vector<int>& cost) {
        int n = cost.size();

        vector<int> dp(n);
        dp[n-1] = cost[n-1];
        dp[n-2] = cost[n-2];
        // 从右往左
        for(int i=n-3; i>=0; --i)
        // 往后
            dp[i] = min(dp[i+1],dp[i+2]) + cost[i];
        
        return min(dp[0],dp[1]);
    }
};


4、解码方法

(1) 题目解析

        本题的核心是抓住解码的两种状态:

        ① 用一位进行解码,但是它有成功和失败,一旦成功那么dp[i-1]处每一个解法都可以添加一个s[i],反之一旦解码失败,说明到达第i位置处,之前的解码都是0。 

        ② 用两位解码,也是有成功和失败,同样如果解码成功,也就意味着dp[i-2]代表的解法综总和,都可以添加上 (s[i-1],s[i] ) ,反之 为0。

class Solution {
public:
    int numDecodings(string s) {
        int n = s.size();
        vector<int> dp(n);
        dp[0] = s[0] != '0';
        if(n == 1) return dp[0];

        if(s[0] !='0' && s[1] !='0') dp[1] += 1;
        int t=(s[0]-'0') * 10 + s[1] -'0';
         if(t >= 10 && t <= 26) dp[1] += 1;

        for(int i=2; i<n; ++i){
            // 单独解码
            if(s[i] != '0') dp[i] += dp[i-1];
            // 两位解码
            int t = (s[i-1]-'0') * 10 + s[i] -'0';
            if(t >= 10 && t <= 26)
                dp[i] += dp[i-2];
        }
        return dp[n-1];
    }
};

优化版本:

         细心的你肯定能够发现,代码里标注的两处,他们的实现功能似乎是一样的,能否有个方法让代码完成复用呢? 换句话说,就是让我们把dp[2] 这个位置放到循环里面初始化。

class Solution {
public:
    int numDecodings(string s) {
        int n = s.size();
        vector<int> dp(n+1);
        dp[0] = 1;
        dp[1] = s[0] != '0';
        if(n == 1) return dp[1];

        for(int i=2; i<=n; ++i){
            // 因为dp多开了一个 对应到的s内的下标应该-1
            if(s[i-1] != '0') dp[i] += dp[i-1];

            int t = (s[i-2]-'0') * 10 + s[i-1] -'0';
            if(t >= 10 && t <= 26)
                dp[i] += dp[i-2];
        }
        return dp[n];
    }
};

       


5、不同路径

(1) 题目解析

        这类路径题总的来说是很简单的,找到结束位置即可。

class Solution {
public:
    int uniquePaths(int m, int n) {
        vector<vector<int>> dp(m+1,vector<int>(n+1));
        // dp[1][0] = 1
        dp[0][1] = 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][n];
    }
};

       


本篇到此结束,感谢你的阅读。

祝你好运,向阳而生~

 

 

 

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

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

相关文章

CSS基础学习--10 margin(外边距)

一、定义&#xff1a; CSS margin(外边距)属性定义元素周围的空间。 二、margin margin 清除周围的&#xff08;外边框&#xff09;元素区域。margin 没有背景颜色&#xff0c;是完全透明的。 margin 可以单独改变元素的上&#xff0c;下&#xff0c;左&#xff0c;右边距&a…

今天面了个35k字节跳动出来,真是砂纸擦屁股,给我露了一手...

​2023年春招已经结束&#xff0c;很多小伙伴收获不错&#xff0c;拿到了心仪的 offer。 各大论坛和社区里也看见不少小伙伴慷慨地分享了常见的面试题和八股文&#xff0c;为此咱这里也统一做一次大整理和大归类&#xff0c;这也算是划重点了。 俗话说得好&#xff0c;他山之石…

AI 绘画(0):导论

文章目录 导论感谢人员Ai绘画前期准备软件环境硬件条件 Ai绘画介绍Ai绘画简单流程介绍Ai绘画软件介绍参数输入介绍 Ai绘画公约 导论 Ai绘画是最近比较热门的绘画方式&#xff0c;以干掉原画师为口号&#xff0c;引起了激烈的讨论。Ai绘画能否取代人工我们先不谈&#xff0c;但…

一个专科生的 Python 转行之路

自学之路 正式开始学编程是在十月底的样子, 那时候在知乎 flask 话题下看到一个问题 「有多少人按萧井陌大神给出的PythonFlask路线找到工作了&#xff1f;」。就觉得自己也可以啊, 就开始辞职自学 Python,。 刚开始的那一个月确实能够做到每天 10 个小时写代码, 学了大概一个…

java设计模式之:外观模式

前言 举个现实生活中例子&#xff0c;泡茶和去茶馆喝茶的区别&#xff0c;如果是自己泡茶需要自行准备茶叶、茶具和开水&#xff0c;而去茶馆喝茶&#xff0c;最简单的方式就是跟茶馆服务员说想要一杯什么样的茶&#xff0c;是铁观音、碧螺春还是西湖龙井&#xff1f;正因为茶…

互斥锁、自旋锁、读写锁、悲观锁、乐观锁的应用场景

多线程访问共享资源的时候&#xff0c;避免不了资源竞争而导致数据错乱的问题&#xff0c;所以我们通常为了解决这一问题&#xff0c;都会在访问共享资源之前加锁。 最常用的就是互斥锁&#xff0c;当然还有很多种不同的锁&#xff0c;比如自旋锁、读写锁、乐观锁等&#xff0…

数据结构——树和二叉树

文章目录 **一 数的基本概念****1 定义****2 基本术语****3 树的性质** **二 二叉树的概念****1 二叉树的定义和特性****1.1 定义****1.2 特殊的二叉树****1.3 二叉树的性质** **2 二叉树的存储结构****2.1 顺序存储结构****2.2 链式存储结构** **三 二叉树的遍历和线索二叉树*…

Spark SQL数据源的基本操作(更新ing)

文章目录 一、基本操作二、默认数据源&#xff08;一&#xff09;默认数据源Parquet&#xff08;二&#xff09;案例演示读取Parquet文件1、在Spark Shell中演示练习1、将student.txt文件转换成student.parquet练习2、读取student.parquet文件得到学生数据帧&#xff0c;并显示…

K8S minikube本地安装

一. mac安装K8S 1.brew安装 brew install kubectl 2.查看版本 kubectl version --outputjson { "clientVersion": { "major": "1", "minor": "27", "gitVersion": "v1.27.2", &…

基于深度学习的高精度奶牛检测识别系统(PyTorch+Pyside6+YOLOv5模型)

摘要&#xff1a;基于深度学习的高精度奶牛检测识别系统可用于日常生活中或野外来检测与定位奶牛目标&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的奶牛目标检测识别&#xff0c;另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5目标检测模型…

locked勒索病毒利用零日漏洞,企业服务器数据瞬间遭受致命加密

目录 引言&#xff1a; 事件概述&#xff1a; .locked勒索病毒加密算法&#xff1a; 数据恢复建议&#xff1a; locked勒索病毒数据恢复案例&#xff1a; 什么叫零日漏洞&#xff1f; 对策建议&#xff1a; 引言&#xff1a; 近日&#xff0c;网络安全界再次爆发了一起…

RK3588平台开发系列讲解(系统篇)开机启动原因

文章目录 一、系统开机启动原因二、开机启动场景沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇章主要讲解平台系统开机启动原因介绍。 一、系统开机启动原因 开机原因记录文件在/proc/sys/kernel/boot_reason,那么开机后可以从这个文件中读取数值来获知本次开机…

锁升级:无锁、偏向锁、轻量级锁、重量级锁

锁升级 JDK 1.6之前&#xff0c;synchronized 还是一个重量级锁&#xff0c;是一个效率比较低下的锁。但是在JDK 1.6后&#xff0c;JVM为了提高锁的获取与释放效率对synchronized 进行了优化&#xff0c;引入了偏向锁和轻量级锁 &#xff0c;从此以后锁的状态就有了四种&#…

开源SCRM营销平台MarketGo-数据管理

一、概述 企业在私域运营的场景下&#xff0c;系统在运行中会产生一些用户数据和行为数据。 用户数据包含年龄&#xff0c;性别&#xff0c;生日&#xff0c;电话&#xff0c;用户标签&#xff0c;还有用户和员工的关系等信息。行为数据包含在SCRM中创建活动的用户事件&#…

自学黑客(网络安全)?一般人我劝你还是算了吧!

前言 博主本人 18年就读于一所普通的本科学校&#xff0c;21年 6 月在三年经验的时候顺利通过校招实习面试进入大厂&#xff0c;现就职于某大厂安全联合实验室。 我为啥说自学黑客&#xff08;网络安全&#xff09;&#xff0c;一般人我还是劝你算了吧。因为我就是那个不一般的…

【C++】c++11的新特性——右值引用/移动语义/lambda表达式

文章目录 C11介绍1. 统一的列表初始化1.1 {}初始化1.2 std::initializer_list 2. 一些关键字2.1 auto2.2 decltype2.3 nullptr 3. 范围for4. 右值引用和移动语义&#xff08;重点&#xff09;4.1 左值引用和右值引用4.2 右值引用的应用4.3 总结 5. 万能引用和完美转发6. 新的类…

mysql小表驱动大表

摘要&#xff1a; 小表驱动大表为了减少匹配时的数据量 判断谁做小表时&#xff0c;是比较算上过滤条件后的数量 left join时手动设置小表驱动大表 inner join时优化器会自动小表驱动大表 course–100条数据 student_info–100w条数据 优化器会选择小表驱动大表&#xff08;这里…

使用VMware Workstation一步一步安装Rocky Linux 9

目录 目录 背景 准备阶段 新建虚拟机 安装Rocky Linux 进入系统 背景 Rocky Linux 简介 企业Linux&#xff0c;社区方式。 Rocky Linux是一个开源的企业操作系统&#xff0c;旨在与红帽企业Linux100%兼容。社区正在大力发展。 Rocky Linux 9.2 于2023年5月16日发布&a…

计算机组成原理(六)指令系统

一、指令的基本格式 1.1机器指令的相关概念 指令集(Instruction Set) 某机器所有机器指令的集合 *定长指令集 指令集中的所有指令长度均相同!取指令控制简单*不定长指令集 指令集中的所有指令长度有长、有短 操作码 (1)长度固定 用于指令字长较长的情况RISC 如IBM370操作码8位…

第四章 Linux网络编程 4.1 网络结构模式 4.2MAC地址、IP地址、端口

第四章 Linux网络编程 4.1 网络结构模式 C/S结构 简介 服务器 - 客户机&#xff0c;即 Client - Server&#xff08;C/S&#xff09;结构。C/S 结构通常采取两层结构。服务器负责数据的管理&#xff0c;客户机负责完成与用户的交互任务。客户机是因特网上访问别人信息的机器…