Longest Increasing Subsequence
很久不写算法了== 写个东西练练手
最长上升子序列
输入n,然后是数组a[ ]的n个元素
输出最长上升子序列的长度
一、最简单的方法复杂度O(n * n)
- DP[ i ] 是以a[ i ] 为结尾的最长上升子序列的长度。
- DP[ i ] = max{DP[ j ] + 1 | j < i && a[ j ] < a[ i ]}
代码:
/* * ===================================================================================== * Filename : LongestIncrSub1.cpp * Description : O(n^2) * Version : a better Algorithm of O(n^2) * Created : 03/22/14 22:03 * Author : Liu Xue Yang (LXY), liuxueyang457@163.com * Motto : How about today? * ===================================================================================== */ #include <iostream> #include <cstdio> #include <climits> #include <cstdlib> ; int dp[MAXN], a[MAXN]; int n, i, j; int main ( int argc, char *argv[] ) { #ifndef ONLINE_JUDGE freopen("LongestIncrSub.txt", "r", stdin); #endif /* ----- not ONLINE_JUDGE ----- */ while ( ~scanf("%d", &n) ) { ; i < n; ++i ) { scanf ( "%d", &a[i] ); dp[i] = INT_MAX; } ; i < n; ++i ) { ; j < n; ++j ) { || dp[j-] < a[i] ) { if ( dp[j] > a[i] ) { dp[j] = a[i]; } } } } ; ; j >= ; --j ) { if ( dp[j] != INT_MAX ) { result = j + ; break; } } printf ( "%d\n", result ); } return EXIT_SUCCESS; } /* ---------- end of function main ---------- */
二、因为长度相同的几个不同的子序列中,最末位数字最小的在之后比较有优势,所以用DP针对这个最小的末尾元素求解。
DP[ i ] 表示长度为 i + 1的上升子序列中末尾元素的最小值
从前往后扫描数组a[ ],对于每一个元素a[ i ],只需要在DP[ ] 数组中找到应该插入的位置。
if j == 0 || a[ i ] > DP[ j-1 ]
DP[ j ] = min{ DP[ j ], a[ i ]}
由于对于每个a[ i ] 都要扫描一遍DP[ ] 数组,所以复杂度还是O(n * n)
代码:
/* * ===================================================================================== * Filename : LongestIncrSub1.cpp * Description : O(n^2) * Version : a better Algorithm of O(n^2) * Created : 03/22/14 22:03 * Author : Liu Xue Yang (LXY), liuxueyang457@163.com * Motto : How about today? * ===================================================================================== */ #include <iostream> #include <cstdio> #include <climits> #include <cstdlib> ; int dp[MAXN], a[MAXN]; int n, i, j; int main ( int argc, char *argv[] ) { #ifndef ONLINE_JUDGE freopen("LongestIncrSub.txt", "r", stdin); #endif /* ----- not ONLINE_JUDGE ----- */ while ( ~scanf("%d", &n) ) { ; i < n; ++i ) { scanf ( "%d", &a[i] ); dp[i] = INT_MAX; } ; i < n; ++i ) { ; j < n; ++j ) { || dp[j-] < a[i] ) { if ( dp[j] > a[i] ) { dp[j] = a[i]; } } } } ; ; j >= ; --j ) { if ( dp[j] != INT_MAX ) { result = j + ; break; } } printf ( "%d\n", result ); } return EXIT_SUCCESS; } /* ---------- end of function main ---------- */
三、对于上一个算法,在DP[ ]数组中找a[ i ]元素的插入位置的时候,采用的是线性查找,由于DP[ ]这个数组是有序的,所以可以采用二分,这要复杂度就降到了O(nlogn),可以用STL函数lower_bound用来找第一个大于等于a[ i ]的位置。
代码:
/* * ===================================================================================== * Filename : LongestIncrSub2.cpp * Description : A better solution * Version : algorithm of O(nlogn) * Created : 03/22/14 22:37 * Author : Liu Xue Yang (LXY), liuxueyang457@163.com * Motto : How about today? * ===================================================================================== */ #include <iostream> #include <cstdio> #include <cstdlib> #include <climits> #include <algorithm> using namespace std; ; int a[MAXN], dp[MAXN]; int i, n, result; int main ( int argc, char *argv[] ) { #ifndef ONLINE_JUDGE freopen("LongestIncrSub.txt", "r", stdin); #endif /* ----- not ONLINE_JUDGE ----- */ while ( ~scanf("%d", &n) ) { fill(dp, dp + n, INT_MAX); ; i < n; ++i ) { scanf ( "%d", &a[i] ); } ; i < n; ++i ) { *lower_bound(dp, dp + n, a[i]) = a[i]; } result = lower_bound(dp, dp + n, INT_MAX) - dp; printf ( "%d\n", result ); } return EXIT_SUCCESS; } /* ---------- end of function main ---------- */
Source Code on GitHub
四、如何打印出最长上升子序列呢?
用一个position数组,position[ i ] 表示位置 i 的数字在上升子序列中的位置。也就是,插入dp数组中的位置。
比如
然后在position数组中从后往前找到第一次出现的3对应的a[ i ] = 8,然后接着找第一次出现的2对应的a[ i ] = 3,然后接着找第一次出现的1对应的a[ i ] = 2,最后接着
找第一次出现的0对应的a[ i ] = -7
所以,-7, 2, 3, 8就是最长上升子序列的一个解。这个解是在序列中最后出现的。
代码:
/* * ===================================================================================== * Filename : LongestIncrSub2.cpp * Description : A better solution * Version : algorithm of O(nlogn) * Created : 03/22/14 22:37 * Author : Liu Xue Yang (LXY), liuxueyang457@163.com * Motto : How about today? * ===================================================================================== */ #include <iostream> #include <cstdio> #include <cstdlib> #include <climits> #include <algorithm> using namespace std; ; int a[MAXN], dp[MAXN], position[MAXN], sub[MAXN]; int i, n, result; int main ( int argc, char *argv[] ) { #ifndef ONLINE_JUDGE // freopen("LongestIncrSub.txt", "r", stdin); #endif /* ----- not ONLINE_JUDGE ----- */ while ( ~scanf("%d", &n) ) { fill(dp, dp + n, INT_MAX); ; i < n; ++i ) { scanf ( "%d", &a[i] ); } int *tmp; ; i < n; ++i ) { tmp = lower_bound(dp, dp + n, a[i]); position[i] = tmp - dp; *tmp = a[i]; } result = lower_bound(dp, dp + n, INT_MAX) - dp; printf ( "%d\n", result ); ; ; i >= ; --i ) { if ( t == position[i] ) { sub[t] = a[i]; --t; } } ; i < result; ++i ) { if ( i ) { printf ( " " ); } printf ( "%d", sub[i] ); } printf ( "\n" ); } return EXIT_SUCCESS; } /* ---------- end of function main ---------- */
所有的代码在git里面
Longest Increasing Subsequence的更多相关文章
- [LeetCode] Longest Increasing Subsequence 最长递增子序列
Given an unsorted array of integers, find the length of longest increasing subsequence. For example, ...
- [tem]Longest Increasing Subsequence(LIS)
Longest Increasing Subsequence(LIS) 一个美丽的名字 非常经典的线性结构dp [朴素]:O(n^2) d(i)=max{0,d(j) :j<i&& ...
- [LintCode] Longest Increasing Subsequence 最长递增子序列
Given a sequence of integers, find the longest increasing subsequence (LIS). You code should return ...
- Leetcode 300 Longest Increasing Subsequence
Given an unsorted array of integers, find the length of longest increasing subsequence. For example, ...
- [LeetCode] Longest Increasing Subsequence
Longest Increasing Subsequence Given an unsorted array of integers, find the length of longest incre ...
- The Longest Increasing Subsequence (LIS)
传送门 The task is to find the length of the longest subsequence in a given array of integers such that ...
- 300. Longest Increasing Subsequence
题目: Given an unsorted array of integers, find the length of longest increasing subsequence. For exam ...
- SPOJ LIS2 Another Longest Increasing Subsequence Problem 三维偏序最长链 CDQ分治
Another Longest Increasing Subsequence Problem Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://a ...
- leetcode@ [300] Longest Increasing Subsequence (记忆化搜索)
https://leetcode.com/problems/longest-increasing-subsequence/ Given an unsorted array of integers, f ...
- [Leetcode] Binary search, DP--300. Longest Increasing Subsequence
Given an unsorted array of integers, find the length of longest increasing subsequence. For example, ...
随机推荐
- 在CentOS6.8上面安装Python3.5
以前每次装Linux,升级Python,都会一堆问题,然后Google,本来想着记录一下,结果问题太多了,也就记不住了,这次特地记了下来. 在CentOS6.8上面安装Python3.5我的系统是Ce ...
- DevExpress gridControl 设置分组
有些代码非常有用,但是用的时候就记不清怎么写,所以就在这里打个草稿. //设置组汇总 private void SetSummation() { this.gridViewShipment.Group ...
- 关于sql 2005 版本问题
win7可以安装:标准版 其他的都安装不了 win2003 2008 :可以安装任何版本
- 火狐和IE浏览器的兼容问题汇总
1.window.event code=(navigator.appName="Netscape")?event.which:event.keycode; 2.event.x mx ...
- VMware虚拟机无法ping通/分配虚拟IP/远程访问的问题的解决方案:
最近老板要写俩web系统,没有自己的服务器,没办法,只好先借用下学院的服务器做下测试调试.那好,问题来了~ 学院的服务器不是我一个人在维护,经常有其他人登进登出(!!!担心文件丢失啊!!!),硬伤!! ...
- SharePoint SC "Audit Settings"功能与CSOM的对应
博客地址:http://blog.csdn.net/FoxDave SharePoint网站集中有个关于审计的功能:"Site collection audit settings&quo ...
- NLPIR(ICTCLAS)分析包的使用记录
前段时间使用了HanLP一个纯JAVA分词工具包,后来老大说分词效果不是很好,需要换一个分词工具.于是推荐了一个分词工具——NLPIR,它是中科院XXX研发的一个分词工具.这个分词工具只用C/C++写 ...
- HTTP协议用的TCP但是只建立单向连接
作者:IronTech链接:https://www.zhihu.com/question/20085992/answer/71742030来源:知乎著作权归作者所有,转载请联系作者获得授权. 下面的解 ...
- SQL 基本知识
四个基础语法 1. insert into 表名 (列名) [values] 值列表 insert into 表名 values 值列表 [扩展]插入多行: 1. insert into <表名 ...
- NOIP 考前 高斯消元练习
POJ 1830 列出n个方程右边为最后的情况 每一行代表第几个灯的情况,每一行代表是否按第几个按钮写出方程即可. #include <cstdio> #include <cstri ...