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

最长上升子序列

输入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多线程之 基本概念

    一.线程的五种状态 1. 新建状态(New)         : 线程对象被创建后,就进入了新建状态.例如,Thread thread = new Thread().2. 就绪状态(Runnable) ...

  2. TCP协议与UDP协议的区别

    TCP协议与UDP协议的区别(转) 首先咱们弄清楚,TCP协议和UCP协议与TCP/IP协议的联系,很多人犯糊涂了,一直都是说TCP/IP协议与UDP协议的区别,我觉得这是没有从本质上弄清楚网络通信! ...

  3. Linux网络编程(多人在线聊天系统)

    一.首先是服务器的建立 首先是一个信号终止程序,发信号ctrl+c终止程序,而是是初始化网络通信. 创建一个描述符负责绑定服务器和监听服务器接收客户端的消息. socket()->sockadd ...

  4. what is SVD and how to calculate it

    http://web.mit.edu/be.400/www/SVD/Singular_Value_Decomposition.htm SVD是研究地震波运动极性化的一个方法.

  5. 利用python实现爬虫爬取某招聘网站,北京地区岗位名称包含某关键字的所有岗位平均月薪

    #通过输入的关键字,爬取北京地区某岗位的平均月薪 # -*- coding: utf-8 -*- import re import requests import time import lxml.h ...

  6. beacon帧

    1.MAC头部 解释: ① Version 版本号  目前为止802.11只有一个版本,所以协议编号为0 ② Type 00表示管理帧,01表示控制帧,10表示数据帧 ③ Subtype 和Type一 ...

  7. What does it mean to “delegate to a sister class” via virtual inheritance?

    Consider the following example: class Base { public: ; ; }; class Der1 : public virtual Base { publi ...

  8. 获取局域网中指定IP或是主机名称的所有文件夹及其搜索文件

    最近做个功能在局域网中所有指定文件,于是花了点精力完成了部分功能,先贴上 using System; using System.Collections.Generic; using System.Co ...

  9. CSS Animation

    div { /* Chrome, Safari, Opera 等使用webkit引擎的浏览器*/ -webkit-animation-name: myfirst; /*规定 @keyframes 动画 ...

  10. nginx 在windows平台上对asp.net做反向代理

    代理服务器 当客户机向站点提出请求时,请求将转到代理服务器.然后,代理服务器通过防火墙中的特定通路,将客户机的请求发送到内容服务器.内容服务器再通过该通道将结果回传给代理服务器.代理服务器将检索到的信 ...