算法学习——LeetCode力扣动态规划篇1(509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯、62. 不同路径、63. 不同路径 II)

算法学习——LeetCode力扣动态规划篇1

在这里插入图片描述

509. 斐波那契数

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

描述

斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:

F(0) = 0,F(1) = 1
F(n) = F(n - 1) + F(n - 2),其中 n > 1
给定 n ,请计算 F(n) 。

示例

示例 1:

输入:n = 2
输出:1
解释:F(2) = F(1) + F(0) = 1 + 0 = 1

示例 2:

输入:n = 3
输出:2
解释:F(3) = F(2) + F(1) = 1 + 1 = 2

示例 3:

输入:n = 4
输出:3
解释:F(4) = F(3) + F(2) = 2 + 1 = 3

提示:

0 <= n <= 30

代码解析

迭代法
class Solution {
public:
    int fib(int n) {
        if(n <=1 ) return n;
        int pre0 = 0 , pre1 = 1;
        int num = n-2;

        while(num--)
        {
            int tmp = pre0 + pre1;
            pre0 = pre1;
            pre1 = tmp; 
        }

        return pre0+pre1;
    }
};

动态规划(DP)
class Solution {
public:
    int fib(int n) {
        if( n<=1 ) return n;
        vector<int> dp(n+1);
        dp[0]=0;
        dp[1]=1;

        for(int i = 2 ; i<dp.size();i++)
        {
            dp[i] = dp[i-1] + dp[i-2];
        }

        return dp[n];
    }
};

70. 爬楼梯

70. 爬楼梯 - 力扣(LeetCode)

描述

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

示例

示例 1:

输入:n = 2
输出:2
解释:有两种方法可以爬到楼顶。

  1. 1 阶 + 1 阶
  2. 2 阶

示例 2:

输入:n = 3
输出:3
解释:有三种方法可以爬到楼顶。

  1. 1 阶 + 1 阶 + 1 阶
  2. 1 阶 + 2 阶
  3. 2 阶 + 1 阶

提示

1 <= n <= 45

代码解析

动态规划

爬到第一层楼梯有一种方法,爬到二层楼梯有两种方法。
那么第一层楼梯再跨两步就到第三层 ,第二层楼梯再跨一步就到第三层。
所以到第三层楼梯的状态可以由第二层楼梯 和 到第一层楼梯状态推导出来,那么就可以想到动态规划了。

我们来分析一下,动规五部曲:

定义一个一维数组来记录不同楼层的状态

确定dp数组以及下标的含义
dp[i]: 爬到第i层楼梯,有dp[i]种方法

从dp[i]的定义可以看出,dp[i] 可以有两个方向推出来。

首先是dp[i - 1],上i-1层楼梯,有dp[i - 1]种方法,那么再一步跳一个台阶不就是dp[i]了么。

还有就是dp[i - 2],上i-2层楼梯,有dp[i - 2]种方法,那么再一步跳两个台阶不就是dp[i]了么。

那么dp[i]就是 dp[i - 1]与dp[i - 2]之和!

所以dp[i] = dp[i - 1] + dp[i - 2] 。

我相信dp[1] = 1,dp[2] = 2,这个初始化大家应该都没有争议的。

所以我的原则是:不考虑dp[0]如果初始化,只初始化dp[1] = 1,dp[2] = 2,然后从i = 3开始递推,这样才符合dp[i]的定义。

确定遍历顺序
从递推公式dp[i] = dp[i - 1] + dp[i - 2];中可以看出,遍历顺序一定是从前向后遍历的

class Solution {
public:
    int climbStairs(int n) {
        if(n<=2) return n;
        vector<int> dp(n+1);
        dp[1] = 1;
        dp[2] = 2;

        for(int i=3 ;i<dp.size() ; i++)
        {
            dp[i] = dp[i-1] + dp[i-2]; 
        }
        return dp[n];

    }
};

完全背包

可以转换为完全背包,求排序数的问题

目标值就是楼梯的高度n,价值就是步子的高度1,2

class Solution {
public:
    int climbStairs(int n) {

        vector<int> step = {1,2};
        vector<int> dp(n+1,0);
       
        dp[0]  = 1;
        //求排序数,先遍历背包,后遍历价值
        for(int j=0 ; j<=n  ;j++)
        {
            for(int i=0 ; i<step.size();i++)
            {
                if(j>=step[i])
                {
                    dp[j] += dp[j-step[i]];
                }
                else dp[j] = dp[j];
            }
                
        }
        return dp[n];
    }
};

746. 使用最小花费爬楼梯

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

描述

给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。

你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。

请你计算并返回达到楼梯顶部的最低花费。

示例

示例 1:

输入:cost = [10,15,20]
输出:15
解释:你将从下标为 1 的台阶开始。

  • 支付 15 ,向上爬两个台阶,到达楼梯顶部。
    总花费为 15 。

示例 2:

输入:cost = [1,100,1,1,1,100,1,1,100,1]
输出:6
解释:你将从下标为 0 的台阶开始。

  • 支付 1 ,向上爬两个台阶,到达下标为 2 的台阶。
  • 支付 1 ,向上爬两个台阶,到达下标为 4 的台阶。
  • 支付 1 ,向上爬两个台阶,到达下标为 6 的台阶。
  • 支付 1 ,向上爬一个台阶,到达下标为 7 的台阶。
  • 支付 1 ,向上爬两个台阶,到达下标为 9 的台阶。
  • 支付 1 ,向上爬一个台阶,到达楼梯顶部。
    总花费为 6 。

提示

2 <= cost.length <= 1000
0 <= cost[i] <= 999

代码解析

花最少的钱爬到楼顶
cost是在每一阶台阶,往上走的成本。

dp[i]的定义:到达第i个台阶所花费的最少体力为dp[i]。
可以有两个途径得到dp[i],一个是dp[i-1] 一个是dp[i-2]。因为最多走两步

即从 i-1台阶,花费cost(i-1) 到 i ;和 i-2台阶,花费cost(i-2) 到 i

dp数组如何初始化
dp[i]由dp[i-1],dp[i-2]推出,既然初始化所有的dp[i]是不可能的,那么只初始化dp[0]和dp[1]就够了,其他的最终都是dp[0]dp[1]推出。

class Solution {
public:
    int minCostClimbingStairs(vector<int>& cost) {
       
        vector<int> dp(cost.size()+1); //要到楼顶,要比台阶数多一个
        dp[0] = 0; //从初始到第0个台阶,和第1个台阶花钱
        dp[1] = 0;
        for(int i=2 ; i<dp.size() ; i++) //从第二个台阶开始计算最小的成本
        {
            dp[i] = min(dp[i-2]+cost[i-2] , dp[i-1]+cost[i-1]);
        }
        return dp[cost.size()]; //到比台阶多一级,即到楼顶的最小成本
    }
};

62. 不同路径

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

描述

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。

问总共有多少条不同的路径?

示例

示例 1:
在这里插入图片描述

输入:m = 3, n = 7
输出:28
示例 2:

输入:m = 3, n = 2
输出:3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。

  1. 向右 -> 向下 -> 向下
  2. 向下 -> 向下 -> 向右
  3. 向下 -> 向右 -> 向下

示例 3:

输入:m = 7, n = 3
输出:28
示例 4:

输入:m = 3, n = 3
输出:6

提示

1 <= m, n <= 100
题目数据保证答案小于等于 2 * 109

代码解析

class Solution {
public:
    int uniquePaths(int m, int n) {
       
        if(m <= 1 || n<=1) return 1;
        vector<vector<int>> dp( m+1 , vector<int>(n+1,0));

        dp[1][1] = 1;
        dp[1][2] = 1;
        dp[2][1] = 1;

        for(int i=1 ; i<=m ; i++)
        {
            for(int j=1 ; j<=n ; j++)
            {   
                if(dp[i][j] != 0 ) continue;
                dp[i][j] = dp[i-1][j] + dp[i][j-1];
                // cout<<"i:"<<i<<" j:"<<j<<"   dp:"<<dp[i][j]<<endl;
            }
        }

        return dp[m][n];
    }
};

63. 不同路径 II

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

描述

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish”)。

现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?

网格中的障碍物和空位置分别用 1 和 0 来表示。

示例

示例 1:
在这里插入图片描述

输入:obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]]
输出:2
解释:3x3 网格的正中间有一个障碍物。
从左上角到右下角一共有 2 条不同的路径:

  1. 向右 -> 向右 -> 向下 -> 向下
  2. 向下 -> 向下 -> 向右 -> 向右

示例 2:
在这里插入图片描述

输入:obstacleGrid = [[0,1],[0,0]]
输出:1

提示

m == obstacleGrid.length
n == obstacleGrid[i].length
1 <= m, n <= 100
obstacleGrid[i][j] 为 0 或 1

代码解析

class Solution {
public:
    int uniquePathsWithObstacles(vector<vector<int>>& obstacleGrid) {
        vector<vector<int>> 
        dp(obstacleGrid.size() , vector<int>(obstacleGrid[0].size() , 0));
        
        for(int i=0 ; i<obstacleGrid.size() ; i++)
        {
            for(int j=0 ; j<obstacleGrid[0].size() ;j++)
            {
                if(obstacleGrid[i][j] == 1) continue; //遇到障碍物绕开
                if(i==0 && j==0) dp[0][0] = 1; //起始点
                else if(i==0) dp[i][j] =  dp[i][j-1]; //最边行
                else if(j==0) dp[i][j] =  dp[i-1][j]; //最边列
                else dp[i][j] = dp[i-1][j] + dp[i][j-1]; 
            }
        }
        return dp[obstacleGrid.size()-1][obstacleGrid[0].size()-1];
    }
};

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Nessus【部署 01】Linux环境部署漏洞扫描工具Nessus最新版详细过程分享(下载+安装+注册+激活)

Nessus最新版详细部署过程分享 1. 获取激活码2.主程序下载安装启动2.1 下载2.2安装2.3 启动 3.许可证及插件3.1 许可证获取3.2 插件安装 4.安装总结 Nessus官方网站&#xff1a; https://www.tenable.com/products/nessus/nessus-essentials 及介绍&#xff1a; 国际数据公司&…

WebUI自动化必备技能-HTML和css知识详解

学习web自动化的前提条件&#xff1a;手工测试&#xff08;了解各种测试的知识&#xff09;、学习编程语言、学习Web基础、学习自动化测试工具 、学习自动化测试框架 、需要掌握前端的一些知识&#xff0c;无论学习语言还是前端知识&#xff0c;都是为了接下来的脚本和框架做铺…

DIY 3 种分库分表分片算法,自己写的轮子才吊!

大家好&#xff0c;我是小富&#xff5e; 前言 本文是《ShardingSphere5.x分库分表原理与实战》系列的第六篇&#xff0c;书接上文实现三种自定义分片算法。通过自定义算法&#xff0c;可以根据特定业务需求定制分片策略&#xff0c;以满足不同场景下的性能、扩展性或数据处理…

常见微服务的组件?

注册中心&#xff1a;就是一个服务注册的地方&#xff0c;我们可以把拆分的服务注册到注册中心&#xff0c;这样注册中心就能管理这些服务&#xff0c;服务之间的调用就会很方便&#xff0c;通过服务名就能相互调用。 负载均衡&#xff1a;被调用放的负载均衡&#xff0c;比如…

单位K与ROM/RAM地址转化的关系?

文章目录 如题如图 如题 在单片机开发中&#xff0c;经常会见到多少K空间这样的字眼&#xff1f;我经常会忘记两者之间的关系&#xff0c;每次都要回想一下&#xff0c;才能明白&#xff0c;这次作为笔记记录一下 如图 这是我以前的笔记&#xff0c;平常所说的多少K是指多少K…

如何在jmeter中快速开发性能脚本?这个功能你需要知道。

在使用jmeter做性能测试时 &#xff0c;基本都是针对以下的两种类型的性能测试&#xff1a; 对web系统页面的性能测试 对系统的接口进行性能测试 有页面的可以优先测试页面 &#xff0c;但是如果是APP或小程序的性能测试 &#xff0c;更多的是对接口进行性能测试 。那么接下来…

学会这几点,是搭建产品知识库的关键

现如今&#xff0c;企业都特别看重产品知识库&#xff0c;因为有了它&#xff0c;企业就能更好地管理产品信息&#xff0c;提升客户服务水平&#xff0c;还能帮企业做决策。但是&#xff0c;搭建一个好用、高效的产品知识库&#xff0c;也难倒了不少人。下面&#xff0c;我们一…

记录何凯明在MIT的第一堂课:神经网络发展史

https://www.youtube.com/watch?vZ5qJ9IxSuKo 目录 表征学习 主要特点&#xff1a; 方法和技术&#xff1a; LeNet 全连接层​ 主要特点&#xff1a; 主要特点&#xff1a; 网络结构&#xff1a; AlexNet 主要特点&#xff1a; 网络结构&#xff1a; Sigmoid Re…

设备物联网关在某制造企业中的应用-天拓四方

随着物联网技术的迅猛发展&#xff0c;设备物联网关作为连接物理世界与数字世界的核心组件&#xff0c;其应用已经渗透到工业、农业、医疗等多个领域。本案例将聚焦于设备物联网关在某制造企业中的应用&#xff0c;详细解析其在实际生产中的重要作用。 案例背景 某制造企业面…

代码随想录阅读笔记-二叉树【平衡二叉树】

题目 给定一个二叉树&#xff0c;判断它是否是高度平衡的二叉树。 本题中&#xff0c;一棵高度平衡二叉树定义为&#xff1a;一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。 示例 1: 给定二叉树 [3,9,20,null,null,15,7] 返回 true 。 示例 2: 给定二叉树 [1,2,…

【Entity Framework】EF中的增删改查

【Entity Framework】EF中的增删改查 文章目录 【Entity Framework】EF中的增删改查一、概述二、DbContext数据上下文三、EntityState五个状态值四、EF添加数据4.1 EF Add方式4.2 EF 通过改变对象的状态为 Added4.3 调用方sql4.4 调用存储过程 五、EF修改数据5.1 不查询数据库&…

【SpringCloud】一文详谈Nacos

&#x1f3e1;浩泽学编程&#xff1a;个人主页 &#x1f525; 推荐专栏&#xff1a;《深入浅出SpringBoot》《java对AI的调用开发》 《RabbitMQ》《Spring》《SpringMVC》《项目实战》 &#x1f6f8;学无止境&#xff0c;不骄不躁&#xff0c;知行合一 文章目录 …

陀螺仪传感器,IMU和加速度计的产品和选型

爱普生陀螺仪传感器是一种角速度传感器&#xff0c;作为一种石英电子式陀螺仪芯片&#xff0c;具有温度特性好、功耗低、成本低、稳定性好等特点。目前EPSON主力单轴陀螺仪传感器型号为XV7001BB、XV7011BB、XV7021BB和XV7181BB。针对扫地机器人传感器模组等领域的需要&#xff…

享道出行:容器弹性技术驱动下的智慧出行稳定性实践

作者&#xff1a;郑嘉扬、何杉 前言 享道出行是一家专注于出行服务的专业品牌&#xff0c;是上汽集团实现汽车产业“新四化”&#xff08;即“电动化、智能网联化、共享化、国际化”&#xff09;的重要组成部分。作为上汽集团移动出行战略品牌&#xff0c;享道出行充分利用全…

4、jvm基础知识(四)

有哪些常见的垃圾回收算法&#xff1f; ⚫1960年John McCarthy发布了第一个GC算法&#xff1a;标记-清除算法。 ⚫1963年Marvin L. Minsky 发布了复制算法。 本质上后续所有的垃圾回收算法&#xff0c;都是在上述两种算法的基础上优化而来。 垃圾回收算法-标记清除算法 标记清…

“星际畅聊”来了!电子开启光通信,量子技术领航远程快速通讯

科学家们最近通过使用电脉冲将磁信息成功转换为偏振光信号&#xff0c;开启了一项革命性的量子技术。这一进展预示着未来包括地球与火星间长距离星际光通信在内的通信方式将发生翻天覆地的变化。 这项研究成果于3月27日在《自然》杂志上发表。研究聚焦于自旋电子学领域&#xf…

Gerrit学习

安装Gerrit 以Ubuntu 20.04为例&#xff0c;安装Gerrit容器2.15版本 docker-compose.yml version: 3 services:gerrit:image: gerritcodereview/gerrit:2.15ports:- 8080:8080- 29418:29418volumes:- ./review_site:/var/gerrit/review_siteenvironment:- CANONICAL_WEB_URL…

算法——距离计算

距离计算常用的算法包括欧氏距离、曼哈顿距离、切比雪夫距离、闵可夫斯基距离、余弦相似度等。这些算法在数据挖掘、机器学习和模式识别等领域中被广泛应用。 1.欧氏距离 欧式距离也称欧几里得距离&#xff0c;是最常见的距离度量&#xff0c;衡量的是多维空间中两个点之间的…

Docker容器、Serverless与微服务:腾讯云云原生架构技术实践案例集解析

前言 随着云原生技术的飞速发展&#xff0c;容器化和函数计算正成为企业和开发者关注的焦点。在这一潮流中&#xff0c;腾讯云凭借其卓越的技术实力和深厚的行业积累&#xff0c;发布了《2023腾讯云容器和函数计算技术实践精选集》&#xff0c;为我们提供了一份深入探索云原生…

【编译分析】MSVC编译器函数修饰的返回值问题

在阅读一篇关于函数重载的文章时&#xff0c;作者提到了MSVC进行函数修饰的结果比较gcc更加复杂。 通过查阅GPT发现可以使用vs提供的dumpbin工具查看编译之后的汇编程序相关信息&#xff0c;可以通过下面这条指令进行查看&#xff1a; dumpbin /all test.exe在结果中查看可以找…