题目

最长上升子序列

给定一个整数序列,找到最长上升子序列(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. 开发一个App的成本是多少?

    英文出处:savvyapps.欢迎加入翻译小组. 在最近的一个会议上,一个叫Bob的老顾客引用了<App Savvy>(<放飞App:移动产品经理实战指南>)中探讨研发一个io ...

  2. python pandas/numpy

    import pandas as pdpd.merge(dataframe1,dataframe2,on='common_field',how='outer') replace NaN datafra ...

  3. Java实现UDP之Echo客户端和服务端

    Java实现UDP之Echo客户端和服务端 代码内容 采用UDP协议编写服务器端代码(端口任意) 编写客户机的代码访问该端口 客户机按行输入 服务器将收到的字符流和接收到的时间输出在服务器consol ...

  4. opencv车道线检测

    opencv车道线检测 完成的功能 图像裁剪:通过设定图像ROI区域,拷贝图像获得裁剪图像 反透视变换:用的是老师给的视频,没有对应的变换矩阵.所以建立二维坐标,通过四点映射的方法计算矩阵,进行反透视 ...

  5. Java Day 14

    多线程--线程间通信 对同一个资源进行处理,但是任务却不同 线程间通信--等待唤醒机制 1.wait();   线程处于冻结状态,被wait线程存储在线程池中 2.notify(); 从线程池唤醒一个 ...

  6. Redis基础教程

    说明:本文中涉及的代码是c#所写,连接redis的第三方驱动为ServiceStack.Redis.连接redis的客户端软件为redis-desktop-manager. 一.Redis是什么 Re ...

  7. heap size eclipse 堆内存

    可以根据eclipse 或 myeclipse heapstats 使用情况调整堆内存大小,heap size 设置,-vmargs-Xms256-Xmx1024 ,其中Xms表示初始值,Xmx表示最 ...

  8. 利用 js 实现弹出蒙板(model)功能

    关于 js 实现一个简单的蒙板功能(model) 思路: 创建一个蒙板, 设置蒙板的堆叠顺序保证能将其它元素盖住 position: absolute; top: 0; left: 0; displa ...

  9. 深入探讨Java类加载机制

    一.前言 毕业至今,已经三年光景,平时基本接触不到关于类加载器的技术(工作上),相信很多同行在开始工作后很长一段时间,对于类的加载机制都没有深入的了解过,之前偶然的机会接触了相关的知识,感觉挺有意思, ...

  10. 文件读写器FileRW 1.0发布

    这个软件未发布前,当年被计算机杂志报道过. FileRW 文件读写器 1.0功能介绍:1.可以以各种方式读普通文件和I/O文件.2.可以以各种方式写文件.3.可以配置文件的分享读写方式.4.可以指定文 ...