DP问题(动态规划)
动态规划问题
1.什么是动态规划?
动态规划(Dynamic Programming)是运筹学的一个分支,是求解决策过程最优化的过程。
动态规划一般可分为线性动规,区域动规,树形动规,背包动规四类。
动态规划常常适用于有重叠子问题和最优子结构性质的问题。
上述概念源自百度百科
2.动态规划核心思想
拆分子问题
备忘录,减少重复计算
下面以一个具体案例来理解动态规划的核心思想:
3.爬楼梯问题
题目描述:
假设你正在爬楼梯。需要 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 阶
3.1划分子问题
解题思想:
本问题其实常规解法可以分成多个子问题,爬第n阶楼梯的方法数量,等于 2 部分之和
爬上 n-1n−1 阶楼梯的方法数量。因为再爬1阶就能到第n阶
爬上 n-2n−2 阶楼梯的方法数量,因为再爬2阶就能到第n阶
于是可以得到以下公式:
f(10) = f(9)+f(8) f (9) = f(8) + f(7) f (8) = f(7) + f(6) ... f(3) = f(2) + f(1) 即通用公式为: f(n) = f(n-1) + f(n-2)
但是此时如果直接使用for循环去求解的话,你会发现超出时间限制
你会发现:
要计算原问题 f(10),就需要先计算出子问题 f(9) 和 f(8)
然后要计算 f(9),又要先算出子问题 f(8) 和 f(7),以此类推。
一直到 f(2) 和 f(1),递归树才终止。
递归时间复杂度 = 解决一个子问题时间*子问题个数
一个子问题时间 = f(n-1)+f(n-2),也就是一个加法的操作,所以复杂度是 O(1);
问题个数 = 递归树节点的总数,递归树的总节点 = 2^n-1,所以是复杂度O(2^n)。
因此,我们要考虑如何把已经计算过的值存储到备忘录中,以降低时间复杂度
代码来喽:
class Solution {public int climbStairs(int n) {if(n<=2){return n;}int i1 = 1;int i2 = 2;for(int i=3;i<=n;i++){int temp = i1+i2;i1 = i2;i2 = temp;}return i2;}
}
3.2自底向上的动态规划
动态规划跟带备忘录的递归解法基本思想是一致的,都是减少重复计算,时间复杂度相差不大:
典型特征:
最优子结构
动态规划问题,其实就是一个递推问题。假设当前决策结果是f(n),则最优子结构就是要让 f(n-k) 最优,最优子结构性质就是能让转移到n的状态是最优的,并且与后面的决策没有关系,即让后面的决策安心地使用前面的局部最优解的一种性质.
状态转移方程
边界
重叠子问题
爬楼梯问题中:
f(n-1)和f(n-2) 称为 f(n) 的最优子结构
f(n)= f(n-1)+f(n-2)就称为状态转移方程
f(1) = 1, f(2) = 2 就是边界啦
比如f(10)= f(9)+f(8),f(9) = f(8) + f(7) ,f(8)就是重叠子问题
我们来看下自底向上的解法,从f(1)往f(10)方向,可以看出一个for循环就可以搞定
4.动态规划解题思路
4.1应用场景
如果一个问题,可以把所有可能的答案穷举出来,并且穷举出来后,发现存在重叠子问题,就可以考虑使用动态规划。
适用例题:最长递增子序列、最小编辑距离、背包问题,爬楼梯问题等等
4.2解题思路
自底向上思想
拆分子问题,记住过往,减少重复计算
大致思路:
穷举分析
确定边界
找出规律,确定最优子结构
写出状态转移方程
穷举分析
列举出尽可能多的方法比如:
阶数是1:f(1) = 1
阶数是2:f(2) = 2
阶数是3:f(3) = f(2) + f(1) =3
阶数是4:f(4) = f(3) + f(2) =5
........
阶数是n:f(n) = f(n-1) + f(n-2)
确定边界
通过穷举发现,阶数为1或2的时候,可以知道明确的跳法,当n>=3时,找到了类似于斐波那契数列公式的规律......
找规律,确定最优子结构
f(n) = f(n-1) + f(n-2)
写出状态转移方程
借助前面三步骤,可以写出此问题的状态转移方程:
1 n=1
f(n) = 2 n=2
f(n-1) + f(n-2) n>3
四步走完成以后:
所以我们得到公式 dp[n] = dp[n-1] + dp[n-2]
同时需要初始化 dp[0]=1dp[0]=1 和 dp[1]=1dp[1]=1
时间复杂度:O(n)
代码来喽:
class Solution {public int climbStairs(int n) {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];}
}
代码源自LeetCode优秀题解,博主也写出来了,不过还是想把最优解呈现给大家啦!!!
5. LeetCode例题分析
题目描述:
给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。
示例:
输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,101],因此长度为 4 。
下面按照动态规划的解题思路来走这个问题:
穷举分析
拿[10,9,2,5,3,7,101,18]举例来说:
当nums只有一个元素10时,最长递增子序列是[10],长度是1.
当nums需要加入一个元素9时,最长递增子序列是[10]或者[9],长度是1。
当nums再加入一个元素2时,最长递增子序列是[10]或者[9]或者[2],长度是1。
当nums再加入一个元素5时,最长递增子序列是[2,5],长度是2。
当nums再加入一个元素3时,最长递增子序列是[2,5]或者[2,3],长度是2。
当nums再加入一个元素7时,,最长递增子序列是[2,5,7]或者[2,3,7],长度是3。
..........
分析子问题示例,需找规律
原问题数组nums[i]的最长递增子序列 = 子问题数组nums[i-1]的最长递增子序列/nums[i]结尾的最长递增子序列
最简单边界情况
当nums数组只有一个元素时,最长递增子序列的长度dp(1)=1,当nums数组有两个元素时,dp(2) =2或者1, 因此边界就是dp(1)=1。
确定最优子结构
dp(i) =max(dp(j))+1,存在j属于区间[0,i-1],并且num[i]>num[j]。
状态转移方程
1 (i=1)dp(i)= max(dp(j))+1 ( 0<=j<i且num[j]<num[i] )
代码来喽:
class Solution {public int lengthOfLIS(int[] nums) {int len = nums.length;if (len < 2){return len;}int[] dp = new int[nums.length];dp[0] = 1;int maxs = 1;for (int i = 1; i < len; i++) {dp[i] = 1;for (int j = 0; j < i; j++) {if (nums[j] < nums[i]) {dp[i] = Math.max(dp[i], dp[j] + 1);}}maxs = Math.max(maxs, dp[i]);}return maxs;}
}
心路历程:这类型的题目不止可以利用动态规划的思想来解决,只是博主刚好想回顾一下动态规划所以翻阅了资料总结整理了这篇文章,希望可以帮助到浏览的每一位童鞋!!!
部分 思路and 图源自:微信公众号 - JAVA烂猪皮(gp1106701116)
DP问题(动态规划)相关推荐
- dp套dp(动态规划)
dp套dp 这是一个对于一类动态规划的计数问题的处理方法,问题常常是如果形式确定就可以直接dp,但是现在却要求满足某个要求的所有方案数,一般的处理方法就是一维负责增量构造,其他维度用来表示内部dp状态 ...
- DP(动态规划)总结
1. 写在前面的话 之前写了一篇不像总结的动态规划总结,感觉更像是一个成长历程,所以就打算重写一篇. 2. 对DP简单的总结 dp的题目特点 求最大或者最小值(如背包:价值最大.凑硬币:数量最少--) ...
- POJ1088滑雪问题 简单dp(动态规划)已AC
滑雪 Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 99422 Accepted: 37756 Description ...
- DP(动态规划)是什么?
目录 DP是什么? DP的原理 概念引入 基本思想 基本概念 动态规划问题中的术语 基本结构 适用条件 最优化原理(最优子结构性质) 无后效性 子问题的重叠性 DP是什么? 动态规划(Dynamic ...
- 洛谷P1040 加分二叉树运用区间DP(动态规划)求解
首先放上原题链接 点我,点我进入原题 什么是动态规划? 在这类问题中,可能会有许多可行解.每一个解都对应于一个值,我们希望找到具有最优值的解.而且每次求出的解不是独立的,我们需要逐层推出最优解. 以这 ...
- DP(动态规划)入门(一)
目录 A.经典模版:求一个数列的最大连续子序列和 B.最大不连续子序列和(小偷) C.小偷进阶版 D.跳跃成功与否 E.最短跳跃次数 F.最长递增子序列 G.花费最小爬楼梯 H.乘积最大子数组 I.删 ...
- 关于DFS(深度优先搜索)与DP(动态规划)的思考
DFS与DP的关系 很多情况下,dfs和dp两种解题方法的思路都是很相似的,这两种算法在一定程度上是可以互相转化的. 想到dfs也就常常会想到dp,当然在一些特定的适用场合下除外. dp主要运用了预处 ...
- 【算法】动态规划+“背包九讲”原理超详细讲解+常见dp问题(9种)总结
目录 一.动态规划(DP) 二.背包九讲 (1)完全背包 P1616 疯狂的采药(完全背包) (2)01背包 滚动数组 一维数组 P1048 采药(01背包) 01背包表格图示 (3)多重背包 整数拆 ...
- 动态规划(DP)——通俗易懂!
转自:阮行止 1. 从一个生活问题谈起 先来看看生活中经常遇到的事吧--假设您是个土豪,身上带了足够的1.5.10.20.50.100元面值的钞票.现在您的目标是凑出某个金额w,需要用到尽量少的钞票. ...
- DP动态规划--最大子段和问题
DP–最大子段和问题(动态规划) 问题: 有n个整数组成一个a1,a2,a3,- ,an序列.求其子段和的最大值(子段是连续的) 比如{-2,11,-4,13,-5,-2},最大子段和就是11-4+1 ...
最新文章
- 前端、云与人工智能的碰撞 | GDG广州
- FileSystem close Exception
- 【PAT乙级】1062 最简分数 (20 分)
- PostgreSQL最终获得存储过程
- Altium Designer(三):基础
- python开发面试笔试题_Python测试开发面试笔试题
- 计算机基础知识office软件,计算机基础知识和office办公系列软件的使用(完整版)...
- Annotation释疑
- 【计算机网络】宽带接入技术
- Write 字符输出流
- MATLAB在Linux上报Warning: Unable to create com.mathworks.mde.explorer.Explorer解决方法
- numpy_concatenate函数
- Python基础篇5:输入两个数,求它们的和、差、积、商、余数
- MTK平台闪光灯驱动分析
- excel被密码保护如何破解获得原密码
- 例题5-10 UVa207-PGA Tour Prize Money(WA)
- android虚拟内存管理,安卓手机虚拟内存软件下载(一招教你扩大手机虚拟内存)...
- IT男人必学的20大泡妞妙招(请允许我蛋疼的转一下)
- 计算机毕业设计 Android的汽车租赁租车app
- angular7上传表格文件并展示在页面
热门文章
- 【LOJ #6617】「THUPC 2019」摆家具 / furniture(DP / BSGS / 矩阵快速幂)
- 暗原色原理去雾matlab代码(Matlab)
- 谷歌:昔日屠龙者正在成为“恶龙”?
- 饭店餐饮点餐系统为什么这么受欢迎?
- 手机版linux软件下载,手机助手linux版下载
- python中字符串,列表,元祖,字典,集合详解
- k8s中将flannel网络切换calico网络
- 新东方托福词汇(List 31 ~ List 35)
- XP如何连接带网口的共享打印机
- TIA博途SCL编程学习21_4个数字中的3个数字的排列组合