lintcode:最长上升子序列
题目
最长上升子序列
给定一个整数序列,找到最长上升子序列(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:最长上升子序列的更多相关文章
- lintcode:最长公共子序列
题目 最长公共子序列 给出两个字符串,找到最长公共子序列(LCS),返回LCS的长度. 样例 给出"ABCD" 和 "EDCA",这个LCS是 "A& ...
- C++版 - Lintcode 77-Longest Common Subsequence最长公共子序列(LCS) - 题解
版权声明:本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C++版 - L ...
- LintCode 77: 最长公共子序列
public class Solution { /** * @param A, B: Two string. * @return: the length of the longest common s ...
- lintcode 77.Longest Common Subsequence(最长公共子序列)、79. Longest Common Substring(最长公共子串)
Longest Common Subsequence最长公共子序列: 每个dp位置表示的是第i.j个字母的最长公共子序列 class Solution { public: int findLength ...
- Lintcode--010(最长上升子序列)
给定一个整数序列,找到最长上升子序列(LIS),返回LIS的长度.LIS(longestIncreasingSubsequence) 说明: 最长上升子序列的定义: 最长上升子序列问题是在一个无序的给 ...
- lintcode-76-最长上升子序列
76-最长上升子序列 给定一个整数序列,找到最长上升子序列(LIS),返回LIS的长度. 说明 最长上升子序列的定义: 最长上升子序列问题是在一个无序的给定序列中找到一个尽可能长的由低到高排列的子序列 ...
- 最长回文子序列LCS,最长递增子序列LIS及相互联系
最长公共子序列LCS Lintcode 77. 最长公共子序列 LCS问题是求两个字符串的最长公共子序列 \[ dp[i][j] = \left\{\begin{matrix} & max(d ...
- 用python实现最长公共子序列算法(找到所有最长公共子串)
软件安全的一个小实验,正好复习一下LCS的写法. 实现LCS的算法和算法导论上的方式基本一致,都是先建好两个表,一个存储在(i,j)处当前最长公共子序列长度,另一个存储在(i,j)处的回溯方向. 相对 ...
- 动态规划之最长公共子序列(LCS)
转自:http://segmentfault.com/blog/exploring/ LCS 问题描述 定义: 一个数列 S,如果分别是两个或多个已知数列的子序列,且是所有符合此条件序列中最长的,则 ...
随机推荐
- asp.net web.config 经典模式和集成模式相关配置
<?xml version="1.0"?> <configuration> <!--IIS经典模式下使用--> <system.web&g ...
- [转] Matlab中给信号加高斯白噪声的方法
MATLAB中产生高斯白噪声非常方便,可以直接应用两个函数,一个是WGN,另一个是AWGN.WGN用于产生高斯白噪声,AWGN则用于在某一信号中加入高斯白噪声. 1. WGN:产生高斯白噪声 y = ...
- VBS基础篇 - 内置函数
Date/Time 函数 函数 描述 CDate 把有效的日期和时间表达式转换为日期(Date)类型. Date 返回当前的系统日期. DateAdd 返回已添加指定时间间隔的日期. DateDiff ...
- 委托、匿名委托和lambda表达式
1.委托 在.NET中,委托有点类似于C/C++中的函数指针,但与指针不同的是,委托是一种安全的类型,那么我们就以实现两个数的差为例,先声明一个成员方法: public int CompareTwoV ...
- OS X 使用技巧——访问所有的键盘功能
苹果笔记本电脑和苹果的无线键盘只有一个Delete键,可以删除光标前面的字. 按住Fn键再按Delete键就能删除光标后面的字符. 按住Fn键会把上下方向键的效果变成Page Up / Page Do ...
- [noi2011]道路修建 树形dp
这道题可以说是树形dp的入门题,也可以看成是一道检验[树]这个数据结构的题目: 这道题只能bfs,毕竟10^6的复杂度win下肯定爆栈了: 但是最恶心的还不是这个,实测用printf输出 用cout输 ...
- 关于Web与JS
Web包含的范围比较广, JS只是代码逻辑而已. Web比如HTTP Message, SOAP Message, 浏览器流程,工具等. 不仅仅是代码.
- MySQL复制中slave延迟监控
在MySQL复制环境中,我们通常只根据 Seconds_Behind_Master 的值来判断SLAVE的延迟.这么做大部分情况下尚可接受,但并不够准确,而应该考虑更多因素. 首先,我们先看下SLAV ...
- NumPy的array
1.numpy包中的array数组,用于弥补列表可以存储任意的数据类型的不足,因为有时候我们需要存储某种类型的数据在数组中,这才是数组的本来内涵.我们通过向numpy.array()函数中传递pyth ...
- CF444C DZY Loves Colors
考试完之后打的第一场CF,异常惨烈呀,又只做出了一题了.A题呆滞的看了很久,领悟到了出题者的暗示,应该就是两个点的时候最大吧,不然的话这题肯定特别难敲,YY一发交上去然后就过了.然后就在不停地YY B ...