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

最长上升子序列

输入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. fake gucci outlet perform a couple associated with things in great trust

    Based on my a lot of years of encounter within Taobao, purchase bags must go to the high reputation ...

  2. 支付宝集成后报错ALI38173

    原因: 支付时传的参数不正确. 出现这个错误, 说明支付功能已经集成成功, 前后台核对下参数就能找到原因了.

  3. ios 真机调试 could not find Developer Disk Image

    同事不小心把iphone测试机升级到了最新系统, 真机调试以前的项目时候不能运行, 提示could not find Developer Disk Image. 原因:缺少最新系统9.3的镜像 解决办 ...

  4. LeetCode之Unique Binry Search Trees

    4月份很快就过半了,最近都在看WPF,有点落伍了...本来想写一点读书笔记的,还没想好要怎么写.所以为了能够达到每月一篇博客的目标,今天先说一个LeetCode上的面试题:Unique Binary ...

  5. javascript页面加载完执行事件

    <script type="text/javascript" language="JavaScript"> //: 判断网页是否加载完成 docum ...

  6. web前端基础篇⑩

    1.960栅格式布局法屏幕分辨率为1024*768.采用接 main宽为960px的布局方式12列式:每格60px 间距20px 3 6 3版 三格式布局(最常用)16列式:每格40px 间距20px ...

  7. CSS中box-sizing属性的理解与部分用法

    今天看了一些关于box-sizing的一些资料,在这里整理一下,希望也能对大家有所帮助. box-sizing是CSS的一个属性,很好的解决了盒模型的相关问题.CSS中的盒模型(Box model)分 ...

  8. 虚拟机下Linux读取USB设备的问题虚拟机下Linux无法读取USB设备的解决方案

    我们在虚拟机中识别USB设备有三种情况导致Linux系统不能读取到USB设备: 1. .当虚拟机的USB服务没有开启的时候 2. 若虚拟机的USB连接的设置选项没有设置好 3. Widows抢先一步, ...

  9. php web系统多域名登录失败解决方法

    下面只是简单的逻辑结构,对于正式的系统需要做具体的处理. 这里需要注意的是:加解密一定需要做安全验证.但是这个方法也不够完美,两个站点必须有相同一级域名:另外这种完全基于cookie的方式,安全性不够 ...

  10. SQL-数学、字符串、时间日期函数和类型转换

    --数学函数 --ABS绝对值,select ABS(-99)--ceiling取上限,select CEILING(4.5)--floor去下限select FLOOR(4.5)--power 几次 ...