【算法题】动态规划基础阶段之 爬楼梯 和 杨辉三角

news2024/11/17 20:21:47

动态规划基础阶段之爬楼梯和杨辉三角

  • 前言
  • 二、爬楼梯
    • 2.1、思路
    • 2.2、代码实现
  • 三、杨辉三角
    • 3.1、思路
    • 3.2、代码实现
  • 四、杨辉三角2(进阶)
  • 总结

前言

动态规划(Dynamic Programming,简称 DP)是一种解决多阶段决策过程最优化问题的方法。它是一种将复杂问题分解成重叠子问题的策略,通过维护每个子问题的最优解来推导出问题的最优解。

动态规划的主要思想是利用已求解的子问题的最优解来推导出更大问题的最优解,从而避免了重复计算。因此,动态规划通常采用自底向上的方式进行求解,先求解出小规模的问题,然后逐步推导出更大规模的问题,直到求解出整个问题的最优解。

动态规划通常包括以下几个基本步骤:

  1. 定义状态:将问题划分为若干个子问题,并定义状态表示子问题的解;
  2. 定义状态转移方程:根据子问题之间的关系,设计状态转移方程,即如何从已知状态推导出未知状态的计算过程;
  3. 确定初始状态:定义最小的子问题的解;
  4. 自底向上求解:按照状态转移方程,计算出所有状态的最优解;
  5. 根据最优解构造问题的解。

动态规划可以解决许多实际问题,例如最短路径问题、背包问题、最长公共子序列问题、编辑距离问题等。同时,动态规划也是许多其他算法的核心思想,例如分治算法、贪心算法等。

动态规划是一种解决多阶段决策过程最优化问题的方法,它将复杂问题分解成重叠子问题,通过维护每个子问题的最优解来推导出问题的最优解。动态规划包括定义状态、设计状态转移方程、确定初始状态、自底向上求解和构造问题解等步骤。动态规划可以解决许多实际问题,也是其他算法的核心思想之一。

二、爬楼梯

假设你正在爬楼梯。需要 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 阶

来源:力扣(LeetCode)。

2.1、思路

本问题其实常规解法可以分成多个子问题,爬第n阶楼梯的方法数量,等于 2 部分之和:

  1. 爬上n−1 阶楼梯的方法数量。因为再爬1阶就能到第n阶。
  2. 爬上n−2 阶楼梯的方法数量,因为再爬2阶就能到第n阶。

所以我们得到公式 :
dp[n]=dp[n−1]+dp[n−2]
同时需要初始化 dp[0]=1 和 dp[1]=1。
时间复杂度:O(n)。
在这里插入图片描述

2.2、代码实现

class Solution {
public:
    int climbStairs(int n) {
        if(n<2)
            return 1;
        int *dp=new int[n+1];
        dp[0]=1;
        dp[1]=1;
        for(int i=2;i<=n;i++)
        {
            dp[i]=dp[i-1]+dp[i-2];
        }
        return dp[n];

    }
};

上述代码动态分配一个数组,造成算法的空间复杂度为O(N),由于每次只要最近的两次结果,我们可以只保存最近的两次结果,而不保存所有的结果,即滚动数组。优化代码如下:

class Solution {
public:
    int climbStairs(int n) {
        int pre1=1,pre2=1,cur=1;
        for(int i=2;i<=n;i++)
        {
            cur=pre1+pre2;
            pre1=pre2;
            pre2=cur;
        }
        return cur;

    }
};

三、杨辉三角

给定一个非负整数 numRows,生成「杨辉三角」的前 numRows 行。

在「杨辉三角」中,每个数是它左上方和右上方的数的和。

在这里插入图片描述

示例 1:

输入: numRows = 5
输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]

示例 2:

输入: numRows = 1
输出: [[1]]

来源:力扣(LeetCode)。

3.1、思路

从第三行开始,除了开始和末尾的位置上的元素,其余位置上的元素都是由上方的元素以及上方左侧的元素相加得到的,此时就很容易的到从第三行开始状态转移方程为dp[i][j] = dp[i - 1][j] + dp[i - 1][j - 1],之后就可轻松求解。

3.2、代码实现

class Solution {
public:
    vector<vector<int>> generate(int numRows) {
        vector<vector<int>> res(numRows);
        for(int i=0;i<numRows;i++)
        {
            res[i].resize(i+1);
            res[i][0]=res[i][i]=1;
            for(int j=1;j<i;j++)
            {
                res[i][j]=res[i-1][j-1]+res[i-1][j];
            }

        }
        return res;
    }
};

时间复杂度: O ( n u m R o w s 2 ) O(numRows^2) O(numRows2)

空间复杂度:O(1);不考虑返回值的空间占用。

四、杨辉三角2(进阶)

给定一个非负索引 rowIndex,返回「杨辉三角」的第 rowIndex 行。

在「杨辉三角」中,每个数是它左上方和右上方的数的和。
在这里插入图片描述
示例 1:

输入: rowIndex = 3
输出: [1,3,3,1]

示例 2:

输入: rowIndex = 0
输出: [1]

示例 3:

输入: rowIndex = 1
输出: [1,1]

来源:力扣(LeetCode)。

思路:递推的方式,保存杨辉三角的所有结果,只返回需要的那行数组。

代码实现:

class Solution {
public:
    vector<int> getRow(int rowIndex) {
        vector<vector<int>> res(rowIndex+1);
        for(int i=0;i<=rowIndex;i++)
        {
            res[i].resize(i+1);
            res[i][0]=res[i][i]=1;
            for(int j=1;j<i;j++)
            {
                res[i][j]=res[i-1][j-1]+res[i-1][j];
            }
        }
        return res[rowIndex];
    }
};

注意到对第 i+1 行的计算仅用到了第 i 行的数据,因此可以使用滚动数组的思想优化空间复杂度。

class Solution {
public:
    vector<int> getRow(int rowIndex) {
        vector<int> pre, cur;
        for (int i = 0; i <= rowIndex; ++i) {
            cur.resize(i + 1);
            cur[0] = cur[i] = 1;
            for (int j = 1; j < i; ++j) {
                cur[j] = pre[j - 1] + pre[j];
            }
            pre = cur;
        }
        return pre;
    }
};

时间复杂度: O ( r o w I n d e x 2 ) O(rowIndex^2) O(rowIndex2)

空间复杂度:O(1);不考虑返回值的空间占用。

总结

动态规划(Dynamic Programming)是一种解决多阶段决策最优化问题的方法,它将复杂问题分解成重叠子问题并通过维护每个子问题的最优解来推导出问题的最优解。动态规划可以解决许多实际问题,例如最短路径问题、背包问题、最长公共子序列问题、编辑距离问题等。

动态规划的基本思想是利用已求解的子问题的最优解来推导出更大问题的最优解,从而避免了重复计算。它通常采用自底向上的方式进行求解,先求解出小规模的问题,然后逐步推导出更大规模的问题,直到求解出整个问题的最优解。

动态规划通常包括以下几个基本步骤:

  1. 定义状态:将问题划分为若干个子问题,并定义状态表示子问题的解;
  2. 定义状态转移方程:根据子问题之间的关系,设计状态转移方程,即如何从已知状态推导出未知状态的计算过程;
  3. 确定初始状态:定义最小的子问题的解;
  4. 自底向上求解:按照状态转移方程,计算出所有状态的最优解;
  5. 根据最优解构造问题的解。

动态规划的时间复杂度通常为 O ( n 2 ) O(n^2) O(n2) O ( n 3 ) O(n^3) O(n3),空间复杂度为O(n),其中n表示问题规模。在实际应用中,为了减少空间复杂度,通常可以使用滚动数组等技巧来优化动态规划算法。

在这里插入图片描述

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

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

相关文章

脱机下载程序

一&#xff0c;脱机下载工具 Mini-Pro V2 版 二&#xff0c;配置stm32CubeIDE 生成hex文件 三&#xff0c;脱机下载步骤 1&#xff0c;连接设备&#xff0c;选择芯片 2&#xff0c; 添加固件。 3&#xff0c;选项字节。 4&#xff0c;生成镜像文件&#xff0c;这个文件包含了…

Mysql索引失效情况及避免方式【案例分析】

索引失效情况及避免方式 建表数据sql CREATE TABLE staffs( id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(24)NOT NULL DEFAULT COMMENT姓名, age INT NOT NULL DEFAULT 0 COMMENT年龄, pos VARCHAR(20) NOT NULL DEFAULT COMMENT职位, add_time TIMESTAMP NOT NULL DEF…

json数据、日期数据的参数传递及响应

文章目录 1.json数据传参1.1 postman如何发送json数据1.2 发送json数据&#xff0c;控制器如何接收 2. 日期类型参数传递2.1 日期类型参数如何指定格式 3.响应数据3.1 ResponseBody注解的使用 1.json数据传参 首先在maven中添加json坐标 1.1 postman如何发送json数据 1.2 发…

00后测试用例写的实在是.......

实在是太强了&#xff0c;00后测试用例写的比我还好&#xff0c;简直是无地自容… 经常看到无论是刚入职场的新人&#xff0c;还是工作了一段时间的老人&#xff0c;都会对编写测试用例感到困扰&#xff1f;例如&#xff1a; 如何编写测试用例&#xff1f; 作为一个测试新人…

以太网频谱

Speed频谱100BASE-TX1GBASE-T2.5GBASE-T5GBASE-T10GBASE-T

网络程序——定时器

网络程序还有一种需要处理的常用事件——定时事件。服务器程序通常管理着众多定时事件&#xff0c;因此如何有效地组织这些定时事件&#xff0c;使之能在预期的时间点被触发且不影响服务器的主要逻辑&#xff0c;对于服务器的性能有着至关重要的影响。为此&#xff0c;我们要将…

递归 到底应该怎么理解?怎么写递归的代码

今天和大家一起来讨论一下递归&#xff1a; 我们尽可能使按照解题的思路来讨论递归&#xff0c;对于这个在计算机内部具体是怎样实现的&#xff0c;我们不做深入讨论&#xff0c;这里仅仅是简单的讨论一下&#xff1a; 求1 ~ n序列的和&#xff1a;1 2 3 ... n&#xff1…

pwn学习day1——ELF文件结构

0x01 介绍 ELF&#xff08;Executable and Linkable Format&#xff09;是一种常见的可执行文件和共享库格式&#xff0c;其结构如下&#xff1a; ELF header&#xff1a;包含了 ELF 文件的基本属性信息。Program header table&#xff1a;描述了程序在内存中的加载情况&…

Gogs私服搭建

1. Gogs介绍 官网地址&#xff1a;https://gogs.io 文档地址&#xff1a;https://gogs.io/docs Gogs&#xff0c;全称为Go Git Service&#xff0c;是一个基于 Go 语言开发的Git服务。它提供了一个类似于GitHub的界面和功能&#xff0c;允许您在自己的服务器上搭建私有的Git仓库…

幂律智能联合智谱AI发布千亿参数级法律垂直大模型PowerLawGLM

前言 2023年是当之无愧的“大模型之年”&#xff0c;据瑞银集团的一份报告显示&#xff0c;ChatGPT推出仅仅两个月后&#xff0c;月活用户已经突破了1亿&#xff0c;成为史上用户增长速度最快的消费级应用程序。 在炙热的大模型赛道里&#xff0c;基于中文大模型的发布也是层…

二叉树OJ题:LeetCode--104.二叉树的最大深度

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下LeetCode中第104道二叉树OJ题&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; 数据结构与算法专栏&#xff1a;数据结构与算法 个 人…

SAP从入门到放弃系列之工艺路线-子工序-Part2

文章目录 概述使用场景子工序内容1、 维护工序控制码2、维护子工序的工资类型3、作业标准值4、用户定义字段5、通过维护子工序的作业类型数据后&#xff0c;点击汇总标准值&#xff0c;工序的作业类型值可以通过子工序进行累计6、可以设置子工序是否带入生产订单 注意事项&…

selenium通过xpath定位text换行的元素

DOM元素&#xff08;该元素是换行的&#xff0c;不能通过普通xpath定位&#xff09;&#xff1a; 可使用下面xpath定位该div //div[./text()/following-sibling::text()"点" and ./text()"5"] 解释一下就是&#xff1a;定位“子节点的text是[5] 且 子节点…

自然语言处理(概念)

1、 RNN模型简介 1.2传统RNN模型 2、LSTM模型 3、GRU模型 5、注意力机制 6、人名分类器 7 、BERT 8、Transformer 的结构是什么样子的&#xff1f; 各个子模块有什么作用&#xff1f; 8.1 Encoder模块 8.2 Decoder模块 8.3 Transformer 结构中的Decoder端具体输入是什么&#…

C# wpf 附加属性实现任意控件拖动调整大小

摘自这里 https://blog.csdn.net/u013113678/article/details/121719278 调试效果如下 using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using Syst…

vue修改数据后页面不重新渲染

使用vue&#xff0c;遇到几次修改了对象的属性后&#xff0c;页面并不重新渲染 一、直接添加属性的问题 <template><div><p v-for"(value,key) in item" :key"key">{{ value }}</p><button click"addProperty">…

【Linux】在Ubuntu下部署nginx——nginx的负载均衡

介绍 这里是小编成长之路的历程&#xff0c;也是小编的学习之路。希望和各位大佬们一起成长&#xff01; 以下为小编最喜欢的两句话&#xff1a; 要有最朴素的生活和最遥远的梦想&#xff0c;即使明天天寒地冻&#xff0c;山高水远&#xff0c;路远马亡。 一个人为什么要努力&a…

vs中的一些编码问题

1. 基本概念 文件编码格式 首先vs中编辑&#xff0c;保存文件实际上也是将文件内容以一定的编码格式存储。对于中文字符串 string s "一"; 按不同的编码格式保存后&#xff0c;通过16进制文件查看器&#xff0c;可以看到中文的编码是能对应上的。 开放高级保存…

select和pselect的关于信号打断的实验

select和pslect的man手册 SELECT(2) Linux Programmers Manual SELECT(2)NAMEselect, pselect, FD_CLR, FD_ISSET, FD_SET, FD_ZERO - synchronous I/O …