博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
最长上升子序列(LIS)动态规划
阅读量:6963 次
发布时间:2019-06-27

本文共 3201 字,大约阅读时间需要 10 分钟。

最长上升子序列

  给你n个整数 AA2 ········· An 找出在这个数组里面的最长上升的子序列。例如给你(1,7,3,5,9,4,8),他的上升子序列有(1,7) (3,4,8)等等之类的,但是最长的上升子序列是(1,3,5,8)。

1)n^2算法

  dp[i] 为当前数组里第i个元素时,以a[i]元素为结尾的最长子序列长度。

  动态转移方程是:dp[i] = max ( dp[i] , dp[j] + 1 ) 其中 j<i 且 a[j] < a[i] 。

  

1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 using namespace std;13 #define pb push_back14 #define mp make_pair15 #define ms(a, b) memset((a), (b), sizeof(a))16 //#define LOCAL17 typedef long long LL;18 const int inf = 0x3f3f3f3f;19 const int maxn = 1000+10;20 const LL mod = 1000000000+7;21 int a[maxn];22 int dp[maxn];23 int main()24 {25 #ifdef LOCAL26 freopen("input.txt" , "r", stdin);27 #endif // LOCAL28 int n;29 scanf("%d", &n);30 for(int i=0;i
dp[i])38 dp[i] = dp[j] + 1;39 }40 }41 int ans = 0;42 for(int i=0;i
View Code

 

2)nlogn算法

   

假设存在一个序列d[1..9] = 2 1 5 3 6 4 8 9 7,可以看出来它的LIS长度为5。n

下面一步一步试着找出它。
我们定义一个序列B,然后令 i = 1 to 9 逐个考察这个序列。
此外,我们用一个变量Len来记录现在最长算到多少了

首先,把d[1]有序地放到B里,令B[1] = 2,就是说当只有1一个数字2的时候,长度为1的LIS的最小末尾是2。这时Len=1

然后,把d[2]有序地放到B里,令B[1] = 1,就是说长度为1的LIS的最小末尾是1,d[1]=2已经没用了,很容易理解吧。这时Len=1

接着,d[3] = 5,d[3]>B[1],所以令B[1+1]=B[2]=d[3]=5,就是说长度为2的LIS的最小末尾是5,很容易理解吧。这时候B[1..2] = 1, 5,Len=2

再来,d[4] = 3,它正好加在1,5之间,放在1的位置显然不合适,因为1小于3,长度为1的LIS最小末尾应该是1,这样很容易推知,长度为2的LIS最小末尾是3,于是可以把5淘汰掉,这时候B[1..2] = 1, 3,Len = 2

继续,d[5] = 6,它在3后面,因为B[2] = 3, 而6在3后面,于是很容易可以推知B[3] = 6, 这时B[1..3] = 1, 3, 6,还是很容易理解吧? Len = 3 了噢。

第6个, d[6] = 4,你看它在3和6之间,于是我们就可以把6替换掉,得到B[3] = 4。B[1..3] = 1, 3, 4, Len继续等于3

第7个, d[7] = 8,它很大,比4大,嗯。于是B[4] = 8。Len变成4了

第8个, d[8] = 9,得到B[5] = 9,嗯。Len继续增大,到5了。

最后一个, d[9] = 7,它在B[3] = 4和B[4] = 8之间,所以我们知道,最新的B[4] =7,B[1..5] = 1, 3, 4, 7, 9,Len = 5。

于是我们知道了LIS的长度为5。

!!!!! 注意。这个1,3,4,7,9不是LIS,它只是存储的对应长度LIS的最小末尾。有了这个末尾,我们就可以一个一个地插入数据。虽然最后一个d[9] = 7更新进去对于这组数据没有什么意义,但是如果后面再出现两个数字 8 和 9,那么就可以把8更新到d[5], 9更新到d[6],得出LIS的长度为6。

然后应该发现一件事情了:在B中插入数据是有序的,而且是进行替换而不需要挪动——也就是说,我们可以使用二分查找,将每一个数字的插入时间优化到O(logN)~~~~~于是算法的时间复杂度就降低到了O(NlogN)~!

1 #include 
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 using namespace std;13 #define pb push_back14 #define mp make_pair15 #define ms(a, b) memset((a), (b), sizeof(a))16 //#define LOCAL17 typedef long long LL;18 const int inf = 0x3f3f3f3f;19 const int maxn = 50000+10;20 const LL mod = 1000000000+7;21 int a[maxn];22 int dp[maxn];23 int Binary_search(int key, int len)24 {25 int l=1, r=len+1;26 while(l
> 1;29 if(key>=dp[middle])30 l = middle +1;31 else32 r = middle;33 }34 return l;35 }36 int main()37 {38 #ifdef LOCAL39 freopen("input.txt" , "r", stdin);40 #endif // LOCAL41 int n, len;42 scanf("%d", &n);43 for(int i=0;i
dp[len])49 dp[++len] = a[i];50 else{51 int j = Binary_search(a[i], len);52 dp[j] = a[i];53 }54 }55 printf("%d\n", len);56 return 0;57 }
View Code

 

附上一些练习题:

1)

2)

3)

4)(最长不上升子序列)

5)(最长不上升子序列)

这些题的题解稍后放出。

转载于:https://www.cnblogs.com/denghaiquan/p/6679952.html

你可能感兴趣的文章
设计模式汇总
查看>>
【书签】个人常用网站整理及应用推荐
查看>>
FJUT3565 最大公约数之和(容斥)题解
查看>>
java实现顺序表
查看>>
hibernate.cfg.xml 配置(摘录)
查看>>
LR错误整理
查看>>
hdu4862 2014多校B题/ 费用流(最优情况下用不大于K条路径覆盖)(不同的解法)...
查看>>
shell脚本字符串截取的8种方法
查看>>
xocde 静态类库 相对路径 与 绝对路径
查看>>
记一次业务复杂的解决流程
查看>>
HDFS API 操作
查看>>
Model to Text工具Acceleo使用教程(四)——模板语法
查看>>
[Angular Tutorial] 8 - Templating Links & Images
查看>>
4、Android-数据存储方案(SQLite数据库存储)
查看>>
html5存储
查看>>
在centOS7.2上编译gcc4.1.2
查看>>
.net core使用ViewComponent将页面图片转码成base64
查看>>
[Java web]Spring+Struts2+Hibernate整合过程
查看>>
在Linux安装MySQL
查看>>
java Long、Integer 、Double、Boolean类型 不能直接比较
查看>>