LeetCode 300. Longest Increasing Subsequence最长上升子序列 (C++/Java)
题目:
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 is4.
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)的更多相关文章
- [LeetCode] 300. Longest Increasing Subsequence 最长递增子序列
Given an unsorted array of integers, find the length of longest increasing subsequence. Example: Inp ...
- [leetcode]300. Longest Increasing Subsequence最长递增子序列
Given an unsorted array of integers, find the length of longest increasing subsequence. Example: Inp ...
- 300 Longest Increasing Subsequence 最长上升子序列
给出一个无序的整形数组,找到最长上升子序列的长度.例如,给出 [10, 9, 2, 5, 3, 7, 101, 18],最长的上升子序列是 [2, 3, 7, 101],因此它的长度是4.因为可能会有 ...
- leetcode300. Longest Increasing Subsequence 最长递增子序列 、674. Longest Continuous Increasing Subsequence
Longest Increasing Subsequence 最长递增子序列 子序列不是数组中连续的数. dp表达的意思是以i结尾的最长子序列,而不是前i个数字的最长子序列. 初始化是dp所有的都为1 ...
- [LeetCode] Longest Increasing Subsequence 最长递增子序列
Given an unsorted array of integers, find the length of longest increasing subsequence. For example, ...
- Leetcode 300 Longest Increasing Subsequence
Given an unsorted array of integers, find the length of longest increasing subsequence. For example, ...
- leetcode@ [300] Longest Increasing Subsequence (记忆化搜索)
https://leetcode.com/problems/longest-increasing-subsequence/ Given an unsorted array of integers, f ...
- [leetcode] 300. Longest Increasing Subsequence (Medium)
题意: 求最长增长的子序列的长度. 思路: 利用DP存取以i作为最大点的子序列长度. Runtime: 20 ms, faster than 35.21% of C++ online submissi ...
- [LintCode] Longest Increasing Subsequence 最长递增子序列
Given a sequence of integers, find the longest increasing subsequence (LIS). You code should return ...
随机推荐
- JDBC处理mysql大数据
大数据也称之为LOB(Large Objects),LOB又分为:clob和blob,clob用于存储大文本,blob用于存储二进制数据,例如图像.声音.二进制文等. 在实际开发中,有时是需要用程序把 ...
- 使用maven的profile构建不同环境配置
基本概念说明(resources.filter和profile): 1.profiles定义了各个环境的变量id 2.filters中定义了变量配置文件的地址,其中地址中的环境变量就是上面profil ...
- Mac破解软件下载的几个网站
一.关于破解(盗版)软件的个人看法(可忽略,网址在文末): 1.在经济(预算)允许的范围内,尽量支持正版: 2.软件如衣服,在不同的季节,不同的店铺买价格不一样,国内的一些代理网站经常会打折: 3.作 ...
- 聊聊 Python 的单元测试框架(二):nose 和它的继任者 nose2
作者:HelloGitHub-Prodesire HelloGitHub 的<讲解开源项目>系列,项目地址:https://github.com/HelloGitHub-Team/Arti ...
- java PDF转word的初步实现
package com.springboot.springboot.util; import java.io.File; import java.io.FileOutputStream; import ...
- Hibernate 之 @Query查询
注解 @Query 允许在方法上使用 JPQL. 列如: @Query("select u from User u where u.name=?1 and u.department_id= ...
- Tomcat启动时设置Jdk版本
1. Window版本Tomcat 到bin下的setclasspath.bat文件,在文件的开始处添加如下代码: set JAVA_HOME=D:\Program Files\Java\jdk1.8 ...
- .Net Standard(.Net Core)实现获取配置信息
一.前言 在.Net Framework框架有专门获取webconfig配置的方法供我们使用,但是在.Net Core或者.Net Standard中没有可以直接使用的方法来获取配置文件信息,下面就来 ...
- (七十二)c#Winform自定义控件-雷达图
前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:ht ...
- Http协议基础内容
1.Http协议是什么协议? 客户端和服务器之间的数据传输的格式规范,简称"超文本传输协议". 2.什么是Http协议无状态协议?怎么解决Http协议无状态协议? 1)无状态协议对 ...