当前位置: 首页 > news >正文

【动态规划】

动态规划1

    • 引言
    • 题目
      • 509. 斐波那契数
      • 70. 爬楼梯
      • 746. 使用最小花费爬楼梯
    • 小结
      • 53. 最大子数组和
    • 结语

引言

蓝桥杯快开始了啊,自从报名后还没认真学过算法有`(>﹏<)′,临时抱一下佛脚,一起学学算法。

题目

509. 斐波那契数

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

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

链接: link
相信这题大家都能闭着眼睛都能写出来了。
这是一个最基础的递推题目
递推公式为**F(n) = F(n - 1) + F(n - 2)**

1.定义一个数组arr[n+1], 用来记录n位置的斐波那契数值
2.定义一个循环变量i 然后进行循环F(i) = F(i - 1) + F(i - 2)
3.返回arr[n]

代码:

int fib(int n){if(n<=1){return n;}else{int arr[n+1];arr[0]=0;arr[1]=1;for(int i=2;i<=n;i++){arr[i]=arr[i-1]+arr[i-2];}return arr[n];}
}

70. 爬楼梯

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

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

示例 1:

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

  1. 1 阶 + 1 阶
  2. 2 阶

链接: 爬楼梯

这道题就是斐波那契数列的简单应用,只是在斐波那契数列是套了一层外套

1.当你在n阶楼梯时
2.只能由n-1阶时走一步或者在n-2阶时走两步
3.所以爬到n阶的方法总数等于爬n-1阶时的方法数加上爬到n-2阶的方法数

也就是F(n)=F(n-1)+F(n-2)(状态转移方程)

代码:

int climbStairs(int n){int arr[46]={1,1};for(int i=2;i<=n;i++){arr[i]=arr[i-1]+arr[i-2];}return arr[n];
}

746. 使用最小花费爬楼梯

给你一个整数数组 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

链接: 使用最小花费爬楼梯

这题和之前的爬楼梯很相似,只是从求方案数到求最小值。
求解思路:

当你在 n 阶楼梯时
只能由 n-1 阶时走一步或者在 n-2 阶时走两步
当选择走 n-1 其花费也是走到 n-1 步时的最小花费加上走这一步的花费
n-2 其花费也是走到 n-2 步时的最小花费加上走这一步的花费
arr[n]值就是两者之间的最小值

定义一个数组arr[1001],用来存储走到n阶楼梯时的最小花费

我们可以得出状态转移方程为

arr[i]=min(arr[i-1]+cost[i-1],arr[i-2]+cost[i-2])

代码:

 int min(int a,int b)
{if(a>b)return b;return a;
}int minCostClimbingStairs(int* cost, int costSize){int arr[1001]={0,0};for(int i=2;i<=costSize;i++){arr[i]=min(arr[i-1]+cost[i-1],arr[i-2]+cost[i-2]); }return arr[costSize];
}

小结

从上述三题可以看出动态规划的大致流程

1.设计状态
2.写出状态转移方程
3.设定初始状态
4.执行状态转移
5.返回最终的解

接下来我们在看一个题

53. 最大子数组和

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

子数组 是数组中的一个连续部分。

示例 1:

输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。

示例 2:

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

题解:
定义一个dp[100001]数组,用于储存以nums[n]为结尾的子数组的和的最大值。

然后根据题意可知,dp[n]的值有两种情况:
第一种:

  1. 当dp[n-1]<=0时,
  2. 表示的是以nums[n-1]结尾的所有子数组的最大值小于0,
  3. 此时dp[n]的值应该是arr[n]的值,因为一个数加上一个小于0的数总比原数小。

第二种:

  1. 当dp[n-1]>0时,
  2. dp[n]的值应该取dp[n-1]和dp[n-1]+nums[n]这两数中的最大值

可得状态转移方程dp[n]=max(dp[n-1]+nums[n],nums[n])
设置初始状态 dp[0]=arr[0]

代码:

int max(int i,int j)
{if(i>j)return i;return j;
}int maxSubArray(int* nums, int numsSize){int dp[100001]={};dp[0]=nums[0];int maxval=nums[0];for(int n=1;n<numsSize;n++){dp[n]=max(dp[n-1]+nums[n],nums[n]);maxval=max(maxval,dp[n]);}return maxval;
}

结语

本期动态规划就到这了
我是Tom-猫
如果觉得有帮助的话,记得
一键三连哦ヾ(≧▽≦*)o。

在这里插入图片描述

http://www.lryc.cn/news/33958.html

相关文章:

  • 秒懂算法 | DP概述和常见DP面试题
  • 【C++提高编程】C++全栈体系(二十五)
  • 【云原生】k8s核心技术—集群安全机制 Ingress Helm 持久化存储-20230222
  • 【Linux】实现简易的Shell命令行解释器
  • 再获认可!腾讯安全NDR获Forrester权威推荐
  • 代码审计之旅之百家CMS
  • ONLYOFFICE中利用chatGPT帮助我们策划一场生日派对
  • Java面试题-线程(一)
  • 一篇普通的bug日志——bug的尽头是next吗?
  • Vue 3 第八章:Watch侦听器
  • GlassFish的安装与使用
  • 【java】Java 重写(Override)与重载(Overload)
  • OpenCV-PyQT项目实战(12)项目案例08:多线程视频播放
  • 面向对象设计模式:结构型模式之装饰器模式
  • Unity iOS 无服务器做一个排行榜 GameCenter
  • 现在招个会自动化测试的人是真难呀~你会个锤子的自动化测试
  • OracleDatabase——数据库表空间dmp导出与导入
  • 20张图带你彻底了解ReentrantLock加锁解锁的原理
  • Dockerfile构建Springboot镜像
  • 从深分页查询到覆盖索引
  • Go语言学习的第三天--下部分(Gin框架的基础了解)
  • JDK的动态代理(powernode 文档)(内含源代码)
  • 第1章 多线程基础
  • Linux基本指令(一)
  • el-dialog子组件在mounted周期内获取不到dom?
  • 第九章 opengl之光照(光照贴图)
  • JDK动态代理(powernode CD2207 video)(内含教学视频+源代码)
  • 【Linux】Sudo的隐晦bug引发的一次业务问题排查
  • Java VisualVM 安装 Visual GC 插件图文教程
  • 【C语言】详解静态变量static