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 ...
随机推荐
- 我的MarkDown入门
目录 0.前言 1.软件准备 2.基本语法 2.1斜体&加粗 2.2分级标题 2.3分割线 2.4超链接 2.5列表 2.6引用 2.7插入代码 2.8插入图像 2.9插入表格 2.10目录 ...
- Jenkins教程(五)构建Java服务Docker镜像
本文主旨 主要记录下如何使用Jenkins构建Java服务的Docker镜像,以及手动部署测试下 前期准备 已安装Jenkins 为jenkins用户添加到docker组内 本地装有maven,配置或 ...
- nexus 私服 低配置服务器启动不能访问的问题
1核1G的渣渣服务器启动无法访问. 请更换更高配置的服务器.
- 误删除系列一:linux的bin目录误删除后恢复操作
感言:一失足成千古恨,一不小心就把/usr/bin下所有的命令都删除了,当你以为自己很熟练时,当你以为自己操作对时,可能就是失手的时候,还好这次只是一个测试环境....God 恢复过程:(以下是在vs ...
- 论文阅读 | DeepDrawing: A Deep Learning Approach to Graph Drawing
作者:Yong Wang, Zhihua Jin, Qianwen Wang, Weiwei Cui, Tengfei Ma and Huamin Qu 本文发表于VIS2019, 来自于香港科技大学 ...
- 一篇文章了解Redis数据库
文章原创于公众号:程序猿周先森.本平台不定时更新,喜欢我的文章,欢迎关注我的微信公众号. redis是一个key-value存储系统.它支持存储的value类型相对更多,包括string(字符串).l ...
- php 循环从数据库分页取数据批量修改数据
//批量修改email重复 public function getEmail() { $this->model = app::get('shop')->model('manage'); / ...
- Django之choices选项和富文本编辑器的使用
项目准备 1.创建数据库 create database choices_test default charset utf8; 2.创建一个名为 choices_test 的Django项目: 3.创 ...
- 数据结构之二叉树篇卷一 -- 建立二叉树(With Java)
一.定义二叉树节点类 package tree; public class Node<E> { public E data; public Node<E> lnode; pub ...
- VMware安装出现"已将该虚拟机配置为使用 64 位客户机操作系统"
1.环境:ThinkPad电脑 系统:win10 64位.VMWare运行虚拟机发现提示无法执行64位操作. 2.解决办法: ⑴ 进入BOIS中 ⑵ 选择Security字段,进入Virtualiza ...