很久不写算法了== 写个东西练练手

最长上升子序列

输入n,然后是数组a[ ]的n个元素

输出最长上升子序列的长度

一、最简单的方法复杂度O(n * n)

  1. DP[ i ] 是以a[ i ] 为结尾的最长上升子序列的长度。
  2. 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的更多相关文章

  1. [LeetCode] Longest Increasing Subsequence 最长递增子序列

    Given an unsorted array of integers, find the length of longest increasing subsequence. For example, ...

  2. [tem]Longest Increasing Subsequence(LIS)

    Longest Increasing Subsequence(LIS) 一个美丽的名字 非常经典的线性结构dp [朴素]:O(n^2) d(i)=max{0,d(j) :j<i&& ...

  3. [LintCode] Longest Increasing Subsequence 最长递增子序列

    Given a sequence of integers, find the longest increasing subsequence (LIS). You code should return ...

  4. Leetcode 300 Longest Increasing Subsequence

    Given an unsorted array of integers, find the length of longest increasing subsequence. For example, ...

  5. [LeetCode] Longest Increasing Subsequence

    Longest Increasing Subsequence Given an unsorted array of integers, find the length of longest incre ...

  6. The Longest Increasing Subsequence (LIS)

    传送门 The task is to find the length of the longest subsequence in a given array of integers such that ...

  7. 300. Longest Increasing Subsequence

    题目: Given an unsorted array of integers, find the length of longest increasing subsequence. For exam ...

  8. SPOJ LIS2 Another Longest Increasing Subsequence Problem 三维偏序最长链 CDQ分治

    Another Longest Increasing Subsequence Problem Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://a ...

  9. leetcode@ [300] Longest Increasing Subsequence (记忆化搜索)

    https://leetcode.com/problems/longest-increasing-subsequence/ Given an unsorted array of integers, f ...

  10. [Leetcode] Binary search, DP--300. Longest Increasing Subsequence

    Given an unsorted array of integers, find the length of longest increasing subsequence. For example, ...

随机推荐

  1. C学习

    \a:警报 1.exit(),提前结束程序.include <stdlib.h> 2.getch()无缓存.getchar()有缓存,多条连用时注意末尾换行符否则始终.putchar(). ...

  2. windows8.1下javaweb环境搭建及基本配置(jdk+tomcat+eclipse)

    1.下载安装jdk在无空格的路径下,否则在linux下可能出问题.配置环境变量: a.新建系统变量——JAVA_HOME,值——D:\programming\java\jdk8 // win8下若建为 ...

  3. Oracle表解锁语句

    如果你发现无法对一个表进行修改.删除等操作时,你可以利用以下语句查询是否是该表被锁住了 --查询锁select sess.sid,sess.serial#, lo.oracle_username,lo ...

  4. Python3学习(一)-基础、数据类型、变量、字符串和编码、list&tuple、if、for、while、dict、set、函数与参数

    ##廖雪峰py3笔记 ## '//'这是获得相除后的整数部分 ##a = 10//3 ##print (a) ## '/'获得相除后的结果,为浮点数,结果能整除也也是浮点数 ##b = 10/3 ## ...

  5. python实现的视频下载工具you-get,支持多个国内外主流视频平台

    RT,you-get 是一个视频离线下载工具, https://github.com/soimort/you-get 另一个同类工具 youtube-dl 也是python 实现,虽然名为 youtu ...

  6. ThinkPHP(3)SQL查询语句

    ThinkPHP中对查询语句,包含了基本的查询方式.表达方式.快速查询.区间查询.组合查询.SQL查询.动态查询和子查询. 一.查询方式 ThinkPHP提供了三种基本的查询方式:字符串条件查询.索引 ...

  7. MVC与webservice上传文件(图片和视频),希望帮且到一些朋友

    最近做一个项目,要把图片和视频传到服务器上(网站与图片服务器分开),在网上找了好久,没找到完整的资料. 自己也折腾了半天,才把完整的代码实现完.可能好多朋友都有实现过,没分享代码吧,写得不好希望不要见 ...

  8. APK签名是如何生成的

    零.前言本文以支付宝手机客户端为例,进行剖析到支付宝官网下载当前最新版本:8.0.1 (2014-01-28)文件名为 alipay_wap_main.apkMD5 摘要为 69820edb3cd13 ...

  9. sql的列的说明

    <#@ template debug="true" hostspecific="true" language="C#" #> & ...

  10. 打开现有的pdf,并插入一个图片

    不说了,直接代码 T_ScanUploadData file = _IScanUploadDataAccessService.GetScanUploadData(id); byte[] filedat ...