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 ...
随机推荐
- FreeSql (三十)读写分离
FreeSql 支持数据库读写分离,本功能是客户端的读写分离行为,数据库服务器该怎么配置仍然那样配置,不受本功能影响,为了方便描术后面讲到的[读写分离]都是指客户端的功能支持. 各种数据库的读写方案不 ...
- golang时间转换
1.datetime转换成时间字符串 package main import ( "fmt" "reflect" "time" ) func ...
- Vue2.x-社交网络程序项目的总结
最近几天一直在学习Vue的课程,通过这个项目进行进一步的学习Vue方面的知识.掌握如何使用Vue搭建前端,如何请求Node.js写好的后端接口. 一.实现前后端连载 首先在后端的文件中 vue i ...
- 用Python分析2000款避孕套,得出这些有趣的结论
到现在为止,我们的淘宝教程已经写到了第四篇,前三篇分别是: 第一篇:Python模拟登录淘宝,详细讲解如何使用requests库登录淘宝pc端. 第二篇:淘宝自动登录2.0,新增Cookies序列化, ...
- 查看mysql中的用户和密码
use mysql; select host,user,password from user; 设置密码 set password for root@localhost=password('root' ...
- 阿里巴巴 Sentinel + InfluxDB + Chronograf 实现监控大屏
前言 在上一篇推文中,我们使用时序数据库 InfluxDb 做了流控数据存储,但是数据存储不是目的,分析监控预警才是最终目标,那么问题来了,如何更好的实现呢?用过阿里巴巴 Sentinel 控制台的小 ...
- WordPress安全防护攻略
个人近期做了一个WordPress站点,目前处于内测阶段,虽然公网还没部署起来,但是先在这学习整理一下安全防护的问题. 第一:及时更新WordPress 由于33%的互联网都在使用WordPress站 ...
- 基于windows的Redis后台服务安装卸载管理
首先,需要你进入你的Redis解压根目录,例如,类似于我下图的这样子: 接着打开你的cmd,使用cd命令切换到该目录,或者直接在上图的地址栏输入“cmd”并回车.这里为什么让你先使用资源管理器找到你的 ...
- 基于操作系统原理的Red Hat Linux的基本操作
一.实验目的 1.了解Linux操作系统的启动与登录方法. 2.掌握Red Hat Linux图形用户界面下的基本操作. 3.学会Red Hat Linux基本设置. 二.实验内容 1. 登录 2. ...
- ViewModel 和 ViewModelProvider.Factory:ViewModel 的创建者
本文翻译自:https://medium.com/koderlabs/viewmodel-with-viewmodelprovider-factory-the-creator-of-viewmodel ...