题目

最长上升子序列

给定一个整数序列,找到最长上升子序列(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_Store - 怎样为iOS8应用制作预览视频

    关于iOS 8应用预览视频的话题,从设计.技术规范,到录屏.编辑工具,介绍的都比较详尽:建议收藏,在接下来用的到的时候作以参考.下面进入译文. 最近一两个月里,苹果的世界里出现了很多新东西,比如屏幕更 ...

  2. MVC4.0 WebApi如何设置api支持namespace

    1.自定义HttpControllerSelector /// <summary> /// 设置api支持namespace /// </summary> public cla ...

  3. FPGA中如何实现除法?

    摘自:<xilinx FPGA 开发实用教程> 1)被除数重复的减去除数,直到检测到余数小于除数为止,优点:对于除数与被除数相差较小的情况下合适 2)通过如下图片方式实现+状态机.优点:挺 ...

  4. Python实现kMeans(k均值聚类)

    Python实现kMeans(k均值聚类) 运行环境 Pyhton3 numpy(科学计算包) matplotlib(画图所需,不画图可不必) 计算过程 st=>start: 开始 e=> ...

  5. C# 串口通信总结

    在C#串口通信开发过程中有的产家只提供通信协议,这时候开发人员要自己根据协议来封装方法,有的产家比较人性化提供了封装好的通信协议方法供开发人员调用. 1.只提供通信协议(例如,今年早些时候开发的出钞机 ...

  6. Windows下查看8080进程及结束进程命令

    Windows下查看进程及结束进程命令 1)查看占用8080端口的进程号 >netstat –aon | findstr “8080” 结果:TCP    0.0.0.0:8080        ...

  7. codeforces399D

    题目大意:ainta刷一面n*n的二维墙.墙一开始可能有一些块被刷了.他终止刷墙的前提是墙的每一行每一列都至少有一块被刷.他每一次从n*n的墙随机选择一块,如果这一块没有被刷就刷,刷了就无视,刷墙不计 ...

  8. JS判断用户是否在线的方法

    在以前坐项目的时候,经常碰见通过sessionLisnter来判断用户是否在线的方法,但是由于用户关闭浏览器时不会立刻是否session,因此大部分时候都考虑在页面中通过JS来监控页面是否关闭. 网络 ...

  9. Poj 1255 覆盖的面积 2014-07-28 12:29 116人阅读 评论(0) 收藏

    覆盖的面积 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Sub ...

  10. context--command buffer

    今天看了下 context ,因为要找怎么设置command buffer context为设备提供一些状态的设置和管理command buffer  & const buffer buffe ...