题目

最长上升子序列

给定一个整数序列,找到最长上升子序列(LIS),返回LIS的长度。

样例

给出[5,4,1,2,3],这个LIS是[1,2,3],返回 3

给出[4,2,4,5,3,7],这个LIS是[4,4,5,7],返回 4

挑战

要求时间复杂度为O(n^2) 或者O(nlogn)

说明

最长上升子序列的定义:

  • 最长上升子序列问题是在一个无序的给定序列中找到一个尽可能长的由低到高排列的子序列,这种子序列不一定是连续的或者唯一的。
  • https://en.wikipedia.org/wiki/Longest_common_subsequence_problem

解题

下面是很久前复制网上的程序

public class Solution {
/**
* @param nums: The integer array
* @return: The length of LIS (longest increasing subsequence)
*/
public int longestIncreasingSubsequence(int[] nums) {
// write your code here
int numlen = nums.length;
if(numlen ==0 )
return 0;
int d[] = new int[numlen]; // 以nums[i] 结束的最长升序子序列的长度 默认值是 1 在全部逆序的情况,
// for(int i = 0 ;i< numlen ; i++)
// d[i] = 1;
d[0] = 1;
int dmax = 1;
for(int i = 1 ; i< numlen;i++){
int subdmax = 0; // 这里记录的是以i结束的升序子序列中,去除第i个元素的长度,显然默认是0
for(int j = 0; j< i ;j++){
if(nums[j] <= nums[i]){
subdmax = Math.max(d[j],subdmax);// 求出i所在升序子序列中,去除第i个元素后,最长的升序子序列长度
}
} d[i] = subdmax + 1;
dmax = Math.max(dmax,d[i]); }
return dmax;
}
}

Java Code

下面写下自己的理解

求的最长子序列的数不是连续的,数之间是有间隔的,但是他们是升序的,或者说是非递减的序列。

前面做过一些关于动态规划的题目,都是喜欢定义一个数组,A,A[i] 表示到达当前 i 位置 的某种 意义,如:最大值个数,最小值个数,长度等等。

这里也是定义一个数组sublongest sublongest[i] 表示到i 位置的最长升序子序列的长度。

到达第i 个元素的最长子序列长度是 sublongest[i]  ,则到达第 i + 1 个元素的最长子序列长度 sublongest[i + 1 ]  =   nums[j] <= nums[i] 时候的最长子序列长度 + 1

数组中最大值就是答案了。

            int sublong = 0;
for(int j=0;j<i;j++){
// nums[i] 前面有几个比自己小的数 比自己小的那个数到自己就是一个递增序列
// sublongest[j] j 这个下标对应 nums[j] 这个元素的,
if(nums[j] <= nums[i]){
sublong = Math.max(sublongest[j],sublong);
}
}
sublongest[i] = sublong + 1;

JAVA

public class Solution {
/**
* @param nums: The integer array
* @return: The length of LIS (longest increasing subsequence)
*/
public int longestIncreasingSubsequence(int[] nums) {
// write your code here
if(nums.length ==0 || nums == null)
return 0;
int len = nums.length;
// 记录到当前位置最长升序序列的长度
int sublongest[] = new int[len];
sublongest[0] = 1;
int longest = Integer.MIN_VALUE; for(int i = 1;i<len;i++){
int sublong = 0;
for(int j=0;j<i;j++){
// nums[i] 前面有几个比自己小的数 比自己小的那个数到自己就是一个递增序列
// sublongest[j] j 这个下标对应 nums[j] 这个元素的,
if(nums[j] <= nums[i]){
sublong = Math.max(sublongest[j],sublong);
}
}
sublongest[i] = sublong + 1;
longest = Math.max(sublongest[i],longest);
}
return longest;
}
}

Python

class Solution:
"""
@param nums: The integer array
@return: The length of LIS (longest increasing subsequence)
"""
def longestIncreasingSubsequence(self, nums):
# write your code here
if nums == None or len(nums)==0:
return 0
l = len(nums)
sublongest = [0 for i in range(l)]
sublongest[0] = 1
longest = -1
for i in range(1,l):
sublong = 0
for j in range(0,i):
if nums[j] <= nums[i]:
sublong = max(sublongest[j],sublong)
sublongest[i] = sublong + 1
longest = max(sublongest[i],longest)
return longest

Python Code

上面的时间复杂度都是O(N2),在LeetCode discuss 看到可以利用二分法,时间复杂度是O(NlogN) 同时空间复杂度是O(N)

这里是定义一个List数组,存储这个升序子序列,并且还是动态变化的,对于新来的元素,通过二分查找,插入到这个list数组中,当大于list数组最后一个元素的时候直接在最后插入,如果在list数组中间位置,就直接在中间位置插入,为什么?说明中间位置额那个数比

需要插入的数字大,我们找的是最长的升序子序列,比他大的当然需要被小的替代了,由于list数组是动态变化的,最后list数组的大小就是最长升序子序列,并且其存储的数就是这个升序子序列,上面的方法对这个升序序列不好存储的。同时中间状态的list数组也是原数

组中间位置的最长升序子序列。下面程序很好理解的。

Java

public class Solution {
/**
* @param nums: The integer array
* @return: The length of LIS (longest increasing subsequence)
*/
public int longestIncreasingSubsequence(int[] nums) {
int len = nums.length;
if(nums == null || len ==0)
return 0;
ArrayList<Integer> dp = new ArrayList<Integer>();
for(int i=0;i<len ;i++){
if(dp.isEmpty() || dp.get(dp.size() - 1) <= nums[i])
dp.add(nums[i]);
else{
int index = findFirstLargeEqual(dp,nums[i]);
dp.set(index,nums[i]);// 用指定的元素替代此列表中指定位置上的元素。 }
}
return dp.size();
}
public int findFirstLargeEqual(ArrayList<Integer> list,int num){
int left = 0;
int right = list.size() - 1;
while(left < right){
int mid = (left + right)/2;
if(list.get(mid) <= num)
left = mid + 1;
else
right = mid;
}
return left;
}
}

Python

class Solution:
"""
@param nums: The integer array
@return: The length of LIS (longest increasing subsequence)
"""
def longestIncreasingSubsequence(self, nums):
# write your code here
if nums == None or len(nums) ==0:
return 0
lst = list()
for i in range(len(nums)):
if len(lst) == 0 or lst[len(lst) - 1] <= nums[i]:
lst.append(nums[i])
else:
index = self.findFirstLargeEqual(lst,nums[i])
lst[index] = nums[i]
return len(lst) def findFirstLargeEqual(self,lst,target):
left = 0
right = len(lst) -1
while left < right:
mid = (left + right)/2
if lst[mid] <= target:
left = mid + 1
else:
right = mid
return left

lintcode:最长上升子序列的更多相关文章

  1. lintcode:最长公共子序列

    题目 最长公共子序列 给出两个字符串,找到最长公共子序列(LCS),返回LCS的长度. 样例 给出"ABCD" 和 "EDCA",这个LCS是 "A& ...

  2. C++版 - Lintcode 77-Longest Common Subsequence最长公共子序列(LCS) - 题解

    版权声明:本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C++版 - L ...

  3. LintCode 77: 最长公共子序列

    public class Solution { /** * @param A, B: Two string. * @return: the length of the longest common s ...

  4. lintcode 77.Longest Common Subsequence(最长公共子序列)、79. Longest Common Substring(最长公共子串)

    Longest Common Subsequence最长公共子序列: 每个dp位置表示的是第i.j个字母的最长公共子序列 class Solution { public: int findLength ...

  5. Lintcode--010(最长上升子序列)

    给定一个整数序列,找到最长上升子序列(LIS),返回LIS的长度.LIS(longestIncreasingSubsequence) 说明: 最长上升子序列的定义: 最长上升子序列问题是在一个无序的给 ...

  6. lintcode-76-最长上升子序列

    76-最长上升子序列 给定一个整数序列,找到最长上升子序列(LIS),返回LIS的长度. 说明 最长上升子序列的定义: 最长上升子序列问题是在一个无序的给定序列中找到一个尽可能长的由低到高排列的子序列 ...

  7. 最长回文子序列LCS,最长递增子序列LIS及相互联系

    最长公共子序列LCS Lintcode 77. 最长公共子序列 LCS问题是求两个字符串的最长公共子序列 \[ dp[i][j] = \left\{\begin{matrix} & max(d ...

  8. 用python实现最长公共子序列算法(找到所有最长公共子串)

    软件安全的一个小实验,正好复习一下LCS的写法. 实现LCS的算法和算法导论上的方式基本一致,都是先建好两个表,一个存储在(i,j)处当前最长公共子序列长度,另一个存储在(i,j)处的回溯方向. 相对 ...

  9. 动态规划之最长公共子序列(LCS)

    转自:http://segmentfault.com/blog/exploring/ LCS 问题描述 定义: 一个数列 S,如果分别是两个或多个已知数列的子序列,且是所有符合此条件序列中最长的,则 ...

随机推荐

  1. 51.ISE中的DCM全局时钟转为普通IO

    在用DCM这个IP核时,它的输入时钟为全局时钟引脚输入,输出有两种情况,第一,可以直接接在全局时钟引脚:第二,可以通过ODDR2原语接在普通IO引脚:说下第二种是怎么用的: DCM DCM_INST ...

  2. Sublime Text 3安装Latex

    Sublime Text 3安装Latex 安装环境 Sublime Text 3已安装Package Control 安装过程 进入官网下载安装MikTex,www.miktex.org 进入官网下 ...

  3. P2763: [JLOI2011]飞行路线

    然而WA了呀,这道分层图,也是不明白为什么WA了=-= ; maxn=; points=; type node=record f,t,l:longint; end; var n,m,k,i,j,u,v ...

  4. [Android Training视频系列] 8.3 Dealing with Audio Output Hardware

    用户在播放音乐的时候有多个选择,可以使用内置的扬声器,有线耳机或者是支持A2DP的蓝牙耳机.(补充:A2DP全名是Advanced Audio Distribution Profile 蓝牙音频传输模 ...

  5. 软件工程课后作业——四则运算Ⅲ(C++)

    一.设计思路 题目:可以答题并判断对错,最后显示做对几道题. 在原有的基础上,又拓展了答题模块. 在结构体中添加了answer属性,把输入的答案与正确答案比较,若相等则计数加一. 二.源代码 (1)四 ...

  6. Github的使用以及Git的简单入门 - 课程作业三

    GitHub创建项目 登录GitHub,在个人主页创建项目(repository) 创建后会生成2个文件,README.md和.gitignore.如图 创建本地仓库 如果是第一次使用git的话,需要 ...

  7. 【BZOJ】【3171】【TJOI2013】循环格

    网络流/费用流 最后能走回出发点……说明全部是环= = 而二分图上的环说明什么呢……完备匹配 对于每个点,它都有四个可能的匹配点,且已知它已经(伪)匹配的一个点,那么我们于已知每条(伪)匹配边,我们连 ...

  8. MVC 基础知识

    一. MVC架构1.MVC模式是一种严格实现应用程序各部分隔离的架构模式.隔离:分离关注点,松耦合2.模型(Model) 代表着核心的业务逻辑和数据.模型封装了域实体的属性和行为3.视图(View) ...

  9. Swift-5-流程控制

    // Playground - noun: a place where people can play import UIKit // For-In 循环 // 1 遍历数字区间 ... { prin ...

  10. 在C语言中嵌入汇编语言

    TMS320C28x编译器允许在C程序中嵌入汇编指令,通过下面声明实现: asm(“assembler text”); 其中assembler text指汇编代码.asm指令一般用来处理C/C++语句 ...