最长上升子数列
来源:互联网 发布:淘宝商家怎么交保证金 编辑:程序博客网 时间:2024/06/05 11:18
最长上升子数列
输入
第1行:1个数N,N为序列的长度(2 <= N <= 50000)第2 - N + 1行:每行1个数,对应序列的元素(-10^9 <= S[i] <= 10^9)
输出
输出最长递增子序列的长度。
输入示例
8516824510
输出示例
5
题解(转载):
(LIS Longest Increasing Subsequence)给定一个数列,从中删掉任意若干项剩余的序列叫做它的一个子序列,求它的最长的子序列,满足子序列中的元素是单调递增的。
例如给定序列{1,6,3,5,4},答案是3,因为{1,3,4}和{1,3,5}就是长度最长的两个单增子序列。
处看此题,怎么做? 万能的枚举?枚举全部2^n个子序列,找出最长的,固然可以,就是复杂度太高。我们为什么要枚举呢?因为要知道取了哪些数,其实我们只需要考虑上一个数和取了几个数就可以了吧?因为单增的意思是比前一个数大,我们要加入这个数的时候,只考虑它比之前加入的最后一个数大就可以了。而最长的意思是数的个数最多,我们只要知道数的总个数就可以了,没必要知道具体有哪些数。
让我们尝试一下用动态规划的思考办法。首先设置数列是a1, a2, a3…an,为了方便我们加入一项a0=-∞,后面我们将发现这会给我们带来极大的方便。int f[i]表示以第i个数结尾的最长单调子序列的长度, 那么我们看一下加入ai之前的最后一个数是aj,显然j < i并且aj < ai,我们有f(i) = f(j) + 1,因为往后面延长了一项嘛。那根据这个式子,我们显然应该选择最大的f(j),才能让f(i)最大。
于是我们有了递推关系f(i) = max{f(j)| j < i并且aj < ai} + 1,光有了递推关系还不够,初值呢? f(0) = 0,并且我们加入了a0=-∞,这样对每个i > 0,j总是存在的,大不了就达到下标0了嘛。
例如给定序列{1,6,3,5,4},答案是3,因为{1,3,4}和{1,3,5}就是长度最长的两个单增子序列。
处看此题,怎么做? 万能的枚举?枚举全部2^n个子序列,找出最长的,固然可以,就是复杂度太高。我们为什么要枚举呢?因为要知道取了哪些数,其实我们只需要考虑上一个数和取了几个数就可以了吧?因为单增的意思是比前一个数大,我们要加入这个数的时候,只考虑它比之前加入的最后一个数大就可以了。而最长的意思是数的个数最多,我们只要知道数的总个数就可以了,没必要知道具体有哪些数。
让我们尝试一下用动态规划的思考办法。首先设置数列是a1, a2, a3…an,为了方便我们加入一项a0=-∞,后面我们将发现这会给我们带来极大的方便。int f[i]表示以第i个数结尾的最长单调子序列的长度, 那么我们看一下加入ai之前的最后一个数是aj,显然j < i并且aj < ai,我们有f(i) = f(j) + 1,因为往后面延长了一项嘛。那根据这个式子,我们显然应该选择最大的f(j),才能让f(i)最大。
于是我们有了递推关系f(i) = max{f(j)| j < i并且aj < ai} + 1,光有了递推关系还不够,初值呢? f(0) = 0,并且我们加入了a0=-∞,这样对每个i > 0,j总是存在的,大不了就达到下标0了嘛。
//O(n^2)时间复杂度#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int maxn = 50010;int dp[maxn], a[maxn];int main(){int n;while(scanf("%d",&n)!=EOF){for(int i=0;i<n;++i) scanf("%d",&a[i]); int ans=0; for(int i=0;i<n;++i) { dp[i]=1; for(int j=0;j<i;++j) { if(a[j]<a[i]) dp[i] = max(dp[i], dp[j]+1); } ans=max(dp[i],ans); } printf("%d\n",ans); }return 0;} //O(nlogn)#include <cstdio> #include <algorithm> #define INF 0x3f3f3f using namespace std; int dp[50010],a[50010]; int main() { int n,i,j; while(scanf("%d",&n)!=EOF) { for(i=0;i<n;++i) { scanf("%d",&a[i]); dp[i]=INF; } for(i=0;i<n;++i) *lower_bound(dp,dp+n,a[i])=a[i]; //二分思想 printf("%d\n",lower_bound(dp,dp+n,INF)-dp); } return 0; }
阅读全文
0 0
- 最长上升子数列
- 最长上升子数列
- LintCode397:最长上升连续子数列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 最长上升子序列
- 矩阵取数问题
- Jsp+Servlet+Mysql测试案例
- 嵌入式学习笔记(第八天)系统网络编程
- Python 里面的一些小技巧(持续更新)
- java web基础大总结
- 最长上升子数列
- 基于XILINX FPGA的卷积神经网络(三)
- PAT L2-022 重排链表 (deque双向队列)
- 【HDU 1950】 Bridging signals (最长上升子序列nlogn算法)(二分,动态规划)
- 【CUGBACM15级BC第16场 A】Revenge of Segment Tree
- awk详解(1)
- 最简单的python 爬虫
- myeclipse 导入 play项目
- 递归问题学习三之生成指定字符串的全排序