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, ...
随机推荐
- C学习
\a:警报 1.exit(),提前结束程序.include <stdlib.h> 2.getch()无缓存.getchar()有缓存,多条连用时注意末尾换行符否则始终.putchar(). ...
- windows8.1下javaweb环境搭建及基本配置(jdk+tomcat+eclipse)
1.下载安装jdk在无空格的路径下,否则在linux下可能出问题.配置环境变量: a.新建系统变量——JAVA_HOME,值——D:\programming\java\jdk8 // win8下若建为 ...
- Oracle表解锁语句
如果你发现无法对一个表进行修改.删除等操作时,你可以利用以下语句查询是否是该表被锁住了 --查询锁select sess.sid,sess.serial#, lo.oracle_username,lo ...
- Python3学习(一)-基础、数据类型、变量、字符串和编码、list&tuple、if、for、while、dict、set、函数与参数
##廖雪峰py3笔记 ## '//'这是获得相除后的整数部分 ##a = 10//3 ##print (a) ## '/'获得相除后的结果,为浮点数,结果能整除也也是浮点数 ##b = 10/3 ## ...
- python实现的视频下载工具you-get,支持多个国内外主流视频平台
RT,you-get 是一个视频离线下载工具, https://github.com/soimort/you-get 另一个同类工具 youtube-dl 也是python 实现,虽然名为 youtu ...
- ThinkPHP(3)SQL查询语句
ThinkPHP中对查询语句,包含了基本的查询方式.表达方式.快速查询.区间查询.组合查询.SQL查询.动态查询和子查询. 一.查询方式 ThinkPHP提供了三种基本的查询方式:字符串条件查询.索引 ...
- MVC与webservice上传文件(图片和视频),希望帮且到一些朋友
最近做一个项目,要把图片和视频传到服务器上(网站与图片服务器分开),在网上找了好久,没找到完整的资料. 自己也折腾了半天,才把完整的代码实现完.可能好多朋友都有实现过,没分享代码吧,写得不好希望不要见 ...
- APK签名是如何生成的
零.前言本文以支付宝手机客户端为例,进行剖析到支付宝官网下载当前最新版本:8.0.1 (2014-01-28)文件名为 alipay_wap_main.apkMD5 摘要为 69820edb3cd13 ...
- sql的列的说明
<#@ template debug="true" hostspecific="true" language="C#" #> & ...
- 打开现有的pdf,并插入一个图片
不说了,直接代码 T_ScanUploadData file = _IScanUploadDataAccessService.GetScanUploadData(id); byte[] filedat ...