单调递增子序列

单调子序列包含有单调递增子序列和递减子序列,不失一般性,这里只讨论单调递增子序列。首先,从定义上明确我们的问题。给定序列a1, a2, …, an,如果存在满足下列条件的子序列

ai1<=ai2<=…<=aim, (其中i1<i2<…<im)

即称为一个原序列的长度为m的单调递增子序列,那么,现在的问题是我们要找出一个序列的最长的单调递增子序列。

   

直观上来说,一个序列Sn,它有2n个子序列,枚举所有的子序列,找出其中单调递增的序列,然后返回其中最长的,这样我们的问题就解决了。当然,这个直观的算法在时间上为O(2n*n),它的复杂度增长太快了,所以,我们还应该做得更好一些。

   

于是,我们换个角度思考。假设我们对Sn排序(递增),得到Sn’。那么,Sn和Sn’的最长公共子序列Cm就是我们要求的最长单调递增子序列(如果你不清楚最长公共子序列的定义,just google it)。为什么?假设Cm’是Sn的最长单调子列,且Cm’!=Cm, Cm’的长度大于Cm。由于Cm’是递增的,并且Cm’的每一个元素都来自Sn,所以Cm’一定是Sn’的子列,而Cm’又是Sn的子列,所以Cm’是Sn和Sn’的公共子列,故Cm’的长度一定小于Cm,这与假设矛盾,所以Cm是最长单调子列。理论上我们的算法是正确的,复杂度方面,运用动态规划(dynamic programming)来求解LCS(最长公共子列,Longest-Common-Subsequence),时间上是O(n2),空间上也是O(n2)。于是,对Sn排序需要nlogn的时间,而LCS需要n2,最后,我们的算法时间上是O(n2)。

   

可以看到,通过上面的改进,我们的算法效率得到了很大的提升(从指数增长到多项式增长)。不过,程序设计的乐趣就是它会不断地给我们一些惊喜,所以,就此打住不是我们该做的,于是,更好的算法应该是存在的。

   

对于序列Sn,考虑其长度为i的单调子列(1<=i<=m),这样的子列可能有多个。我们选取这些子列的结尾元素(子列的最后一个元素)的最小值。用Li表示。易知

L1<=L2<=…<=Lm

如果Li>Lj(i<j),那么去掉以Lj结尾的递增子序列的最后j-i个元素,得到一个长度为i的子序列,该序列的结尾元素ak<=Lj<Li,这与Li标识了长度为i的递增子序列的最小结尾元素相矛盾,于是证明了上述结论。现在,我们来寻找Sn对应的L序列,如果我们找到的最大的Li是Lm,那么m就是最大单调子列的长度。下面的方法可以用来维护L。

   

从左至右扫描Sn,对于每一个ai,它可能

(1)    ai<L1,那么L1=ai

(2)    ai>=Lm,那么Lm+1=ai,m=m+1 (其中m是当前见到的最大的L下标)

(3)    Ls<=ai<Ls+1,那么Ls+1=ai

   

扫描完成后,我们也就得到了最长递增子序列的长度。从上述方法可知,对于每一个元素,我们需要对L进行查找操作,由于L有序,所以这个操作为logn,于是总的复杂度为O(nlogn)。优于开始O(n2)的算法。这里给出我的一个实现:(算法并没有返回具体的序列,只是返回长度)

  

复制代码
 1 template <typename T>
2 int LMS (const T * data, int size)
3 ...{
4 if (size <= 0)
5 return 0;
6
7 T * S = new T[size];
8 int S_Count = 1;
9 S[0] = data[0];
10
11 for (int i = 1; i < size; i++)
12 ...{
13 const T & e = data[i];
14 int low = 0, high = S_Count - 1;
15
16 while (low <= high)
17 ...{
18 int mid = (low + high) / 2;
19
20 if (S[mid] == e)
21 break;
22 else if (S[mid] > e)
23 ...{
24 high = mid - 1;
25 }
26 else
27 ...{
28 low = mid + 1;
29 }
30 }
31
32 //well, in this point
33 //high is -1, indicating e is the smallest element.
34 //otherwise, high indicates index of the largest element that is smaller than e
35 if (high == S_Count - 1)
36 S[S_Count++] = e;
37 else
38 S[high + 1] = e;
39 }
40
41 return S_Count;
42 }

转载于:https://www.cnblogs.com/ITXIAZAI/p/4111294.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/545706.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTML文本框内容发生变化时引发事件执行

最近在做的程序中需要这样的一个功能:当HTML文本框内容生发变化时执行JavaScript函数.最初的想法是使用onchange,但这个事件只有当文本框失去焦点时才会触发,后来就找到了onpropertychange事件.如下:<input id"textRoad" type"text" size"15"…

第 1-5 课:深入了解 Java 中的异常处理 + 面试题

在程序开发中,异常处理也是我们经常使用到的模块,只是平常很少去深究异常模块的一些知识点。比如,try-catch 处理要遵循的原则是什么,finally 为什么总是能执行,try-catch 为什么比较消耗程序的执行性能等问题,我们本篇内容都会给出相应的答案,当然还有面试中经常被问到…

java math 类_Java Math类静态双层(double d)示例

java math 类数学班静态双层(双D) (Math Class static double floor(double d)) This method is available in java.lang package. 此方法在java.lang包中可用。 In this method if the value of the given positive argument after decimal point is 0 or greater than 0 so i…

在win server 2003上安装SQL Server 2008的步骤

1.安装Microsoft .NET Framework 3.5 Service Pack 1&#xff0c;下载地址&#xff1a;http://www.microsoft.com/zh-cn/download/confirmation.aspx?id22 2.运行SQL Server 2008安装包&#xff0c;安装过程中会提示需要重启&#xff0c;手动重启。 3.重启后若直接再次运行SQL…

使用onclick跳转到其他页面/跳转到指定url

如果是本页显示可以直接用location,方法如下&#xff1a;①οnclick"javascript:window.location.hrefURL"②οnclick"locationURL"③οnclick"window.location.hrefURL?id11"如果页面中有frame可以将在location前面添加top.mainframe.frames[r…

第 2-1 课:类与 Object + 面试题

类介绍 Java 程序是由若干个类组成的,类也是面向对象编程思想的具体实现。 以下为类的基本使用: public class Cat {// 私有属性private String name;private int age;// 构造方法public Cat() {}// 普通方法public void eat() {System.out.println("吃吃吃");}…

expm1_Java Math类静态double expm1(double d)及其示例

expm1数学类静态double expm1(double d) (Math Class static double expm1(double d)) This method is available in java.lang package. 此方法在java.lang包中可用。 This method is used to return [ the exponential of the given number – 1] in the method or in other …

51单片机常用功能及相关内容

一、基本概念&#xff1a; 1、引脚 图1.1 这里只介绍常用及主要的引脚。 I/O口引脚&#xff1a;P0、P1、P2、P3 P0口&#xff1a;39脚~32脚&#xff0c;双向8位三态I/O口&#xff0c;每个口可独立控制&#xff0c;但内部无上拉电阻&#xff0c;为高阻态&#xff0c;故不能正常…

No monitoring data is available

No monitoring data is available because monitoring is not enabled for this deployment share...注解&#xff1a;没有监测数据是可用的。报错具体信息如下&#xff1a;Assembly: mscorlib Assembly Version: 2.0.0.0 File Version: 2.0.50727.5420 (Win7SP1.050727-5400…

oracle chr()和字符连接

SQL> select chr(105)||chr(32)||chr(108)||chr(111)||chr(118)||chr(101)||chr(32)||chr(121)||chr(111)||chr(117) as hi from dual;

第 1-7 课:数组和排序算法 + 面试题

数组的定义与使用 数组是 Java 编程中最重要的数据结构之一,也是最基本的数据结构,Java 中的常用集合 ArrayList、HashMap 等内部的实现都使用到了数组结构。数组是只能用来存储一种类型的集合,可以通过下标访问数值中的所有元素。 数组的声明方式有以下两种,如整数型数组…

gethours_日期getHours()方法以及JavaScript中的示例

gethoursJavaScript Date getHours()方法 (JavaScript Date getHours() method) getHours() method is a Dates class method and it is used to get the only hours from current time. getHours()方法是Date的类方法&#xff0c;用于获取距当前时间仅有的小时数。 It accept…

单词助手(可联网)

基本功能 1. 可实现对本地词库添加、删除单词功能 2. 可实现查词功能&#xff0c;根据英文查释义&#xff0c;优先从本地词库查询&#xff0c;如果本地词库没有就自动网上查询&#xff0c;并将其添加至本地词库 3. 可实现学习功能&#xff0c;每天50词&#xff0c;可分批次学习…

Unity查安卓Native Crash的方法,定位SO报错函数

需要用到两个工具Il2CppDumper和IDA_Pro&#xff0c;网上可以下到对应的软件 可以看到报错的位置是libil2cpp.so 0000000000AFF820 接下来要做的事情就是找到0000000000AFF820对应的函数是哪个 解包 Il2CppDumper解析so文件和符号表&#xff0c;查看对应的函数表 把apk后缀…

WebApi系列~自主宿主HttpSelfHost的实现

回到目录 宿主一词我们不会陌生&#xff0c;它可以看作是一个基础设施&#xff0c;它为一些服务和功能提供最底层的支持&#xff0c;如你的web应用程序可以运行在iis或者apache上&#xff0c;而这两个东西就是web应用程序的宿主&#xff0c;而今天说的自主宿主SelfHost就是说&a…

第 2-2 课:各种内部类和枚举类 + 面试题

内部类不仅经常出现在各种面试题中,还会在 Java 源码中频频出现,因此只有搞明白了 Java 内部类,才能搞定面试和看懂各种 Java 源码。 内部类 Java 内部类,分为以下四种: 成员内部类静态成员内部类局部内部类匿名内部类下面分别来看这些内部类的使用。 成员内部类 定义…

linux系统层次结构_Linux文件系统层次结构问题和解答

linux系统层次结构This section contains Aptitude Questions and Answers on Linux Filesystem Hierarchy. 本节包含有关Linux文件系统层次结构的 Aptitude问答。 1) There are the following statements that are given below, which of them are correct about Linux File …

plsql developer 安装在win7 64位电脑路径问题

plsql developer 如果安装在win7 64位电脑上&#xff0c;安装目录不能有括号或者中文等特殊字符&#xff0c;默认安装路径是C:\Program Files (x86)。——

第 2-4 课:克隆和序列化 + 面试题

克隆 在开始学习克隆之前,我们先来看看下面的代码,普通的对象复制,存在什么问题? class CloneTest {public static void main(String[] args) throws CloneNotSupportedException {// 等号赋值( 基本类型)int number = 6;int number2 = number;// 修改 number2 的值num…

Java StreamTokenizer whitespaceChars()方法及示例

StreamTokenizer类whitespaceChars()方法 (StreamTokenizer Class whitespaceChars() method) whitespaceChars() method is available in java.io package. whitespaceChars()方法在java.io包中可用。 whitespaceChars() method is used to denotes that all the characters l…