python解题思路公共子序列a[i=b[j_剑指Offer——动态规划算法

剑指Offer——动态规划算法

什么是动态规划?

和分治法一样,动态规划(dynamic programming)是通过组合子问题而解决整个问题的解。

分治法是将问题划分成一些独立的子问题,递归地求解各子问题,然后合并子问题的解。

动态规划适用于子问题不是独立的情况,也就是各子问题包含公共的子子问题。

此时,分治法会做许多不必要的工作,即重复地求解公共的子问题。动态规划算法对每个子问题只求解一次,将其结果保存起来,从而避免每次遇到各个子问题时重新计算答案。

适用范围

最优性原理体现为问题的最优子结构特性。当一个问题的最优解中包含了子问题的最优解时,则称该问题具有最优子结构特性。

最优性原理是动态规划的基础。任何一个问题,如果失去了这个最优性原理的支持,就不可能用动态规划设计求解。

1.问题中的状态满足最优性原理。

2.问题中的状态必须满足无后效性。

所谓无后效性是指:“下一时刻的状态只与当前状态有关,而和当前状态之前的状态无关,当前状态是对以往决策的总结”。

动态规划算法的设计

两种方法:

自顶向下(又称记忆化搜索、备忘录):基本上对应着递归函数实现,从大范围开始计算,要注意不断保存中间结果,避免重复计算

自底向上(递推):从小范围递推计算到大范围

动态规划的重点

递归方程+边界条件

爬楼梯问题

一个人每次只能走一层楼梯或者两层楼梯,问走到第80层楼梯一共有多少种方法。

设DP[i]为走到第i层一共有多少种方法,那么DP[80]即为所求。很显然DP[1]=1, DP[2]=2(走到第一层只有一种方法:就是走一层楼梯;走到第二层有两种方法:走两次一层楼梯或者走一次两层楼梯)。同理,走到第i层楼梯,可以从i-1层走一层,或者从i-2走两层。很容易得到:

递推公式:DP[i]=DP[i-1]+DP[i-2]

边界条件:DP[1]=1   DP[2]=2

(a)自顶向下的解法:

long long dp[81] = {0};/*用于保存中间结果否则会重复计算很多重复的子问题*/

long long DP(int n)

{

if(dp[n])

return dp[n];

if(n == 1)

return 1;

if(n == 2)

return 2;

dp[n] = DP(n-1) + DP(n-2);

return dp[n];

}

(b)自底向上的解法:

int i;

long long dp[81]; /* 注意当n超过75时,结果值将超过int范围 */

dp[1] = 1;

dp[2] = 2;

for(i=3; i <= 80; i++)

dp[i] = dp[i-1] + dp[i-2];

最长上升子序列

对于序列:4 1 2 24,它的最长上升子序列是1 2 4,长度为3。

对于序列:4 2 4 25 6,它的最长上升子序列是2 4 5 6,长度为4。

设a[i]表示原序列,设DP[i]表示以第i个数结尾的最长上升序列的长度,那么很显然想导出DP[i]的值,需要在DP[k](1<=k

递推公式:DP[i]=max(DP[k]+1,DP[i])  1<=k

边界条件:DP[i]=1                   1<=i<=n

算法复杂度为O(n^2)

void RiseSequence(int Array[], int num)

{

#define MAX_LENGTH 30

struct

{

int SequenceValue; /* max length ending with this num */

int PreviousIndex; /* record the previous number */

}ArrayInfo[MAX_LENGTH], temp;

int i;

for(i = 0; i < num; i++)

{

int j;

ArrayInfo[i].SequenceValue = 1;

ArrayInfo[i].PreviousIndex = -1;

for(j = 0; j < i; j++)

{

if(Array[j] < Array[i] && (ArrayInfo[j].SequenceValue + 1 > ArrayInfo[i].SequenceValue))

{

ArrayInfo[i].SequenceValue = ArrayInfo[j].SequenceValue + 1;

ArrayInfo[i].PreviousIndex = j;

}

}

}

temp.SequenceValue = ArrayInfo[0].SequenceValue;

for(i = 1; i < num; i++)

{

if(temp.SequenceValue < ArrayInfo[i].SequenceValue)

{

temp.SequenceValue = ArrayInfo[i].SequenceValue;

temp.PreviousIndex = i;

}

}

for(i = 0; i < temp.SequenceValue; i++)

{

printf("%d ", Array[temp.PreviousIndex]); /* in reverse order */

temp.PreviousIndex = ArrayInfo[temp.PreviousIndex].PreviousIndex;

}

printf("\nthe max rising sequence length is %d\n", temp.SequenceValue);

}

最长公共子序列

给定两个序列X和Y,称序列Z是X和Y的公共子序列如果Z既是X的一个子序列,又是Y的一个子序列。例如,如果X={a,b,c,b,d,a,b} Y={b,d,c,a,b,a} 那么序列{b,c,a}就是X和Y的一个公共子序列,但是它并不是X和Y的最长公共子序列,因为它的长度为3。而同为X和Y公共子序列的{b,c,b,a},长度为4,因为找不到长度为5或更大的公共子序列,所以X和Y的最长公共子序列长度就为4。

假设两个序列数组分别为a,b。定义f(i,j)为计算到a数组第i个数、b数组第j个数时所得到的最长公共子序列的长度。这时有两种情况:

1.假如a[i]=b[j],那么f(i,j)=f(i-1,j-1)+1

2.假如a[i]!=b[j],那么f(i,j)=max(f(i-1,j),f(i,j-1))

边界条件为:f(i,0)=0     1<=i<=len(a)

f(0,j)=0     1<=j<=len(b)

算法复杂度:O(n^2),len(a)表示数组a的长度。

尾声

动态规划绝对不是一两篇文章可以讲清楚的。当然也不是通过一两道题目可以完全学会。学习的关键是用动规的思想去想问题,去设计状态转移方程式。

动态规划还有很多变形,如状态压缩,树形等等。

虽然通常我们用递归的方式分析动态规划问题,但最终都会基于循环去编码。

美文美图

剑指Offer——贪心算法

剑指Offer--贪心算法 一.基本概念 所谓贪心算法是指,在对问题求解时,总是做出在当前看来是最好的选择.也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解.虽然贪心算法不能对 ...

剑指Offer——回溯算法解迷宫问题(java版)

剑指Offer--回溯算法解迷宫问题(java版)   以一个M×N的长方阵表示迷宫,0和1分别表示迷宫中的通路和障碍.设计程序,对任意设定的迷宫,求出从入口到出口的所有通路.   下面我们来详细讲一 ...

剑指Offer——分治算法

剑指Offer--分治算法 基本概念 在计算机科学中,分治法是一种很重要的算法.字面上的解释是"分而治之",就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更 ...

剑指Offer——回溯算法

剑指Offer--回溯算法 什么是回溯法 回溯法实际是穷举算法,按问题某种变化趋势穷举下去,如某状态的变化用完还没有得到最优解,则返回上一种状态继续穷举.回溯法有"通用的解题法"之 ...

《剑指offer》算法题第十二天

今天是算法题系列的最后一天了,但是这个系列并没有包括书上的所有题目,因为正如第一天所说,这些代码是在牛客网上写并且测试的,但是牛客网上并没有涵盖书上所有的题目. 今日题目 ...

《剑指offer》算法题第一天

按照个人计划,从今天开始做上面的算法题,练习平台为牛客网,上面对每道题都有充分的测试实例,感觉还是很不错的.今天下午做了四道题,分别为: 1. 二叉树的深度(书55题) ...

JS数据结构与算法 - 剑指offer二叉树算法题汇总

❗❗ 必看经验 在博主刷题期间,基本上是碰到一道二叉树就不会碰到一道就不会,有时候一个下午都在搞一道题,看别人解题思路就算能看懂,自己写就呵呵了.一气之下不刷了,改而先去把二叉树的基础算法给搞搞懂,然 ...

《剑指offer》算法题第十天

今日题目: 数组中的逆序对 两个链表的第一个公共节点 数字在排序数组中出现的次数 二叉搜索树的第k大节点 字符流中第一个不重复的字符 1. 数组中的逆序对 题目描述: 在数组中的两个数字,如果前面一个 ...

《剑指offer》算法题第十一天

今日题目: 滑动窗口的最大值 扑克牌中的顺子 圆圈中最后剩下的数字 求1+2+3+...+n 不用加减乘除做加法 构建乘积数组 今天的题目比较有意思,可以学到很多知识,包括第1题中的数据结构——双向队 ...

随机推荐

xcodebuild命令行打包发布ipa

配置好证书,然后在命令行转到项目目录 1.清除 EthantekiiMac:CTest ethan$ xcodebuild clean 2.编译 EthantekiiMac:CTest ethan$ ...

sqlite时间比较语法

如下: 字段 > datetime('2000-01-01 01:01:01') AND 字段 < datetime('2001-01-01 01:01:01');

【mongoDB运维篇②】备份与恢复(导入与导出)

导入/导出可以操作的是本地的mongodb服务器,也可以是远程的服务器 所以,都有如下通用选项: -h host 主机 --port port 端口 -u username 用户名 -p passwd ...

ZOJ-3725 Painting Storages DP

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3725 n个点排列,给每个点着色,求其中至少有m个红色的点连续的数 ...

nosql db and javascript performance

http://blog.csdn.net/yiqijinbu/article/details/9053467 http://blog.nosqlfan.com/tags/javascript http ...

MySQL 避免重复数据的批量插入与批量更新

[转发] 导读 我们在向数据库里批量插入数据的时候,会遇到要将原有主键或者unique索引所在记录更新的情况,而如果没有主键或者unique索引冲突的时候,直接执行插入操作. 这种情况下,有三种方式执 ...

TensorFlow资源整理

什么是TensorFlow? TensorFlow 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库.节点(Nodes)在图中表示数学操作,图中的线(edges)则表示 ...

Day11 (黑客成长日记) 爬取网站图片

#导入第三方库# coding:utf-8import requests,re #找到需要爬取的网站'http://www.qqjia.com/sucai/sucai1210.htm' #1>获 ...

shopnc 手机网站配置

完整版SHOPNC下载地址:http://www.fenxiangweb.com/thread-7643-1-1.html SHOPNC手机wap版安装教程 1.进入根目录下mobile/readme ...

安装部署Jenkins服务

1.导入安装包 2.安装安装包 (1).安装JDK和maven 创建jdk存储目录 # mkdir /usr/jdk64/ 解压jdk到存储目录 # tar -zxvf jdk-8u191-linux ...

你可能感兴趣的:(python解题思路公共子序列a[i=b[j_剑指Offer——动态规划算法)