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

最长上升子序列

输入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. java培训第一天--画板

    package day1; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt ...

  2. Java中获取长度length和size的问题

    1.length属性是针对Java中的数组来说的,要求数组的长度可以用其length属性: 2.length()方法是针对字符串来说的,要求一个字符串的长度就要用到它的length()方法: 3.ja ...

  3. win10 Unistack 服务组 占用资源如何解决

    开始菜单>设置>隐私,隐私界面的左侧栏目,找最后一个“后台应用”,把后台运行的应用全部关掉即可

  4. swift 定位

    iOS 8 及以上需要在info.plist文件中添加下面两个属性 NSLocationWhenInUseUsageDescription 使用应用期间 NSLocationAlwaysUsageDe ...

  5. c4,configure the debug environment

    Yesterday I found a tiny C compiler (less than 600 line of C code, containing commits) called " ...

  6. centos 7 下安装numpy、scipy等python包

    本文适用于刚入门的小白,欢迎大牛们批评指正. 因为要开始数据分析,而python又不像R和matlab那么简洁.需要安装的包很多~ 网上找了好多牛人博客,想在centos7下安装numpy,scipy ...

  7. JS 笔记(二) - 函数

    1. 函数的 声明 1) 声明式写法 function j1(id){ alert(id); } 2) 声明匿名函数变量 var j2 = function (a, b) { alert(a + &q ...

  8. js拖拽效果

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. javascript 在ie8中报“缺少标识符、字符串或数字“问题再现:

    开发和测试使用Chrome浏览器比较多,客户反馈某个页面打不开,自己用Chrome打开一切正常,用ie8打开,果然页面展现卡在那儿了,并且报了"缺少标识符.字符串或数字".查看是在 ...

  10. Python开发入门与实战21-订阅事件(subscribe)

    21. 订阅事件(subscribe) 新用户关注微信公众平台,将产生一个订阅事件,即subscribe事件,在新用户关注公众平台后为新用户提供一些简明扼要的公众号说明 事件推送(event): 接收 ...