题目:

Given an unsorted array of integers, find the length of longest increasing subsequence.

Example:

Input: [10,9,2,5,3,7,101,18]
Output: 4
Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4.

Note:

  • There may be more than one LIS combination, it is only necessary for you to return the length.
  • Your algorithm should run in O(n2) complexity.

Follow up: Could you improve it to O(n log n) time complexity?

分析:

给定一个无序的整数数组,找到其中最长上升子序列的长度。

注意此题不要求上升子序列是连续的,我们可以去观察这样一个问题,已知一个序列[16,17,2,3,4]其最大上升子序列是[2,3,4]如果这时候又来一个20,我们这样来看。

如果以4为结尾和20组合,那么我们此时的序列则是[16,17,2,3,4,20]其最大上升子序列是[2,3,4,20],最大长度也就是3+1=4(原来序列以4为结尾的最大上升子序列的长度+1)。

如果以3为结尾和20组合,那么我们此时的序列则是[16,17,2,3,20]其最大上升子序列是[2,3,20],最大长度是2+1。

如果以2为结尾和20组合,那么我们此时的序列则是[16,17,2,20]其最大上升子序列是[2,20],最大长度是1+1。

你可能会问这时候最大上升子序列不应该是[16,17,20]吗?要记住,此时我们求的是以2结尾的最大上升子序列,所以只能是[2,20]。

如果以17为结尾和20组合,那么我们此时的序列则是[16,17,20]其最大上升子序列是[16,17,20],最大长度是2+1。

如果以16为结尾和20组合,那么我们此时的序列则是[16,20]其最大上升子序列是[16,20],最大长度是1+1。

我们可以从头遍历数组,每新来一个元素,便去和以前所有元素去相比,如果新来的元素比当前元素大,则意味着新来的元素可以和以当前元素为结尾的最大上升子序列构成新的最大上升子序列,且新最大上升子序列的长度等于以当前元素为结尾的最大上升子序列的长度+1,这样听起来可能绕口些。我们开辟一个新的数组,大小和原数组一样大,对应位置存储着以此元素为结尾的最大上升子序列的长度。

10              
1              
10 9            
1 1            
10 9 2          
1 1 1          
10 9 2 5        
1 1 1 2        
10 9 2 5 3      
1 1 1 2 3      
10 9 2 5 3 7    
1 1 1 2 2 3    
10 9 2 5 3 7 101  
1 1 1 2 2 3 4  
10 9 2 5 3 7 101 18
1 1 1 2 2 3 4 4

每新来一个元素,都要和前面的每一个元素为结尾的序列去比较能否成为新的上升子序列。最后返回数组中最大的值,即是最大上升子序列的长度,这样时间复杂度是O(n^2)。

现在我们再来说一下O(nlogn)的方法,我们来利用二分搜索来维护一个最有希望的上升子序列的数组dp。

我们知道如果一个序列,[10,20,30,1,2,3.....],很明显1,2,3要比10,20,30更有希望构成最大上升子序列。

给定数列[10,20,30,1,2,3,5]。

先来10,那么此时的最有希望的上升子序列dp:[10].

20,dp:[10,20]

30,dp:[10,20,30]

此时新加进来1,利用二分搜素,将1替换掉10,此时的最有希望的上升子序列为[1,20,30],你可能会问,1在30的后面,无法和20,30构成上升子序列,的确,但是我们要求的是最有希望的,且我们的数组的大小就是最大的上升子序列的长度,如果后面的元素无法构成更大的上升子序列,那么当前数组的大小也已经记录下之前的最大上升子序列的长度,这点不用担心。

1,dp:[1,20,30]

2,dp:[1,2,30]

3,dp:[1,2,3]

5,dp:[1,2,3,5]

此时的dp正是我们求的最有希望的上升子序列,且它的长度正是最大上升子序列的长度。

如果数列是[10,20,30,1,2]

最后求的dp会是[1,2,30],虽然这无法构成上升子序列,但此时数组的大小,正是由之前10,20,30所扩充的,也保存了最大上升子序列的长度。

程序:

C++

//Dynamic
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
if(nums.size() == ) return ;
int longest = ;
vector<int> res(nums.size(), );
for(int i = ; i < nums.size(); ++i){
for(int j = i; j > ; j--){
if(nums[i] > nums[j-]){
res[i] = max(res[i], res[j-]+);
}
}
}
for(auto n:res){
if(longest < n) longest = n;
}
return longest;
}
};
//Dynamic Programming with Binary Search
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
if(nums.size() == ) return ;
vector<int> res;
res.push_back(nums[]);
for(int i = ; i < nums.size(); ++i){
int index = binarySearch(res, nums[i]);
if(index == -)
res[] = nums[i];
else if(index < -)
res.push_back(nums[i]);
else
res[index] = nums[i];
}
return res.size();
}
int binarySearch(vector<int>& v, int num){
if(num < v[]) return -;
if(num > v[v.size()-]) return -(v.size()+);
int l = ;
int r = v.size()-;
int mid;
while(l <= r){
mid = l + (r-l)/;
if(num < v[mid]) r = mid-;
else if(num > v[mid]) l = mid+;
else return mid;
}
return l;
}
};

Java

//Dynamic Programming with Binary Search
class Solution {
public int lengthOfLIS(int[] nums) {
if(nums.length == 0) return 0;
int[] res = new int[nums.length];
int size = 0;
for(int i = 0; i < nums.length; ++i){
int index = Arrays.binarySearch(res, 0, size, nums[i]);
if(index < 0) index = -(index+1);
res[index] = nums[i];
if(index == size) size++;
}
return size;
}
}
//Java binarySearch
// [1] 该搜索键在范围内,但不是数组元素,由1开始计数,得“ - 插入点索引值”;
// [2] 该搜索键在范围内,且是数组元素,由0开始计数,得搜索值的索引值;
// [3] 该搜索键不在范围内,且小于范围(数组)内元素,返回–(fromIndex + 1);
// [4] 该搜索键不在范围内,且大于范围(数组)内元素,返回 –(toIndex + 1)。

LeetCode 300. Longest Increasing Subsequence最长上升子序列 (C++/Java)的更多相关文章

  1. [LeetCode] 300. Longest Increasing Subsequence 最长递增子序列

    Given an unsorted array of integers, find the length of longest increasing subsequence. Example: Inp ...

  2. [leetcode]300. Longest Increasing Subsequence最长递增子序列

    Given an unsorted array of integers, find the length of longest increasing subsequence. Example: Inp ...

  3. 300 Longest Increasing Subsequence 最长上升子序列

    给出一个无序的整形数组,找到最长上升子序列的长度.例如,给出 [10, 9, 2, 5, 3, 7, 101, 18],最长的上升子序列是 [2, 3, 7, 101],因此它的长度是4.因为可能会有 ...

  4. leetcode300. Longest Increasing Subsequence 最长递增子序列 、674. Longest Continuous Increasing Subsequence

    Longest Increasing Subsequence 最长递增子序列 子序列不是数组中连续的数. dp表达的意思是以i结尾的最长子序列,而不是前i个数字的最长子序列. 初始化是dp所有的都为1 ...

  5. [LeetCode] Longest Increasing Subsequence 最长递增子序列

    Given an unsorted array of integers, find the length of longest increasing subsequence. For example, ...

  6. Leetcode 300 Longest Increasing Subsequence

    Given an unsorted array of integers, find the length of longest increasing subsequence. For example, ...

  7. leetcode@ [300] Longest Increasing Subsequence (记忆化搜索)

    https://leetcode.com/problems/longest-increasing-subsequence/ Given an unsorted array of integers, f ...

  8. [leetcode] 300. Longest Increasing Subsequence (Medium)

    题意: 求最长增长的子序列的长度. 思路: 利用DP存取以i作为最大点的子序列长度. Runtime: 20 ms, faster than 35.21% of C++ online submissi ...

  9. [LintCode] Longest Increasing Subsequence 最长递增子序列

    Given a sequence of integers, find the longest increasing subsequence (LIS). You code should return ...

随机推荐

  1. CF785D Anton and School – 2

  2. FreeSql (二十八)事务

    FreeSql实现了四种数据库事务的使用方法,脏读等事务相关方法暂时未提供.主要原因系这些方法各大数据库.甚至引擎的事务级别五花八门较难统一. 事务用于处理数据的一致性,处于同一个事务中的操作是一个U ...

  3. caffe学习一:ubuntu16.04下跑Faster R-CNN demo (基于caffe). (亲测有效,记录经历两天的吐血经历)

    兜兜转转,兜兜转转; 一次有一次,这次终于把Faster R-CNN 跑通了. 重要提示1:在开始跑Faster R-CNN之前一定要搞清楚用的是Python2 还是Python3. 不然你会无限次陷 ...

  4. linux中必备常用支持库的安装(CentOS)

    在CentOS安装软件的时候,可能缺少一部分支持库,而报错.这里首先安装系统常用的支持库.那么在安装的时候就会减少很多的错误的出现 yum install -y gcc gdb strace gcc- ...

  5. C++基础之关联容器

    关联容器 关联容器和顺序容器的本质区别:关联容器是通过键存取和读取元素.顺序容器通过元素在容器中的位置顺序存储和访问元素.因此,关联容器不提供front.push_front.pop_front.ba ...

  6. xshell调用xmanager,打开linux远程桌面

    xshell输入命令:gnome-panel

  7. Java连载35-类总结、空指针异常

    一.总结 1.栈内存中主要存储的是方法体中的局部变量 2.对象内部有实例变量,实例变量存储在堆内存中 3.变量分类:局部变量(方法体中声明):成员变量(方法体外声明) 实例变量(前边修饰符没有stat ...

  8. linux下安装pip(centos)

    centos系统中自带python2.7.5但是却没有pip工具 直接yum install pip会提示没有这个包 解决方案: 需要先安装扩展源EPEL. EPEL(http://fedorapro ...

  9. Java入门系列之hashCode和equals(十二)

    前言 前面两节内容我们详细讲解了Hashtable算法和源码分析,针对散列函数始终逃脱不掉hashCode的计算,本节我们将详细分析hashCode和equals,同时您将会看到本节内容是从<E ...

  10. XLNet预训练模型,看这篇就够了!(代码实现)

    1. 什么是XLNet XLNet 是一个类似 BERT 的模型,而不是完全不同的模型.总之,XLNet是一种通用的自回归预训练方法.它是CMU和Google Brain团队在2019年6月份发布的模 ...