原题链接在这里:https://leetcode.com/problems/longest-increasing-subsequence/

题目:

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

For example,
Given [10, 9, 2, 5, 3, 7, 101, 18],
The longest increasing subsequence is [2, 3, 7, 101], therefore the length is 4. Note that there may be more than one LIS combination, it is only necessary for you to return the length.

Your algorithm should run in O(n^2) complexity.

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

题解:

类似Largest Divisible Subset.

DP问题.

e.g. nums = {5, 3, 4, 8, 6, 7.}

前1个数的LIS长度d(1)=1(序列: 5)

前2个数的LIS长度d(2)=1(序列: 3; 3前面没有比3小的)

前3个数的LIS长度d(3)=2(序列: 3, 4; 4前面有个比它小的3, 所以d(3)=d(2)+1)

前4个数的LIS长度d(4)=3(序列: 3, 4, 8; 8前面比它小的有3个数,所以 d(4)=max{d(1),d(2),d(3)}+1=3)

OK,分析到这,我觉得状态转移方程已经很明显了,如果我们已经求出了d(1)到d(i-1),  那么d(i)可以用下面的状态转移方程得到:

d(i) = max{1, d(j)+1}, 其中j<i && nums[j]<nums[i]

想要求d(i), 就把i前面的各个子序列中, 最后一个数小于nums[i]的序列长度加1, 然后取出最大的长度即为d(i). 当然了,有可能i前面的各个子序列中最后一个数都大于A[i], 那么d(i)=1, 即它自身成为一个长度为1的子序列.

dp[i]表示以nums[i]结尾的LIS.

Time Complexity: O(n^2). Space O(n).

AC Java:

 1 public class Solution {
 2     public int lengthOfLIS(int[] nums) {
 3         if(nums == null || nums.length == 0){
 4             return 0;
 5         }
 6         int max = 1;
 7         int [] dp = new int[nums.length];
 8         for(int i = 0; i<nums.length; i++){
 9             dp[i] = 1;
10             for(int j = 0; j<i; j++){
11                 if(nums[j] < nums[i]){
12                     dp[i] = Math.max(dp[i], dp[j]+1);
13                 }
14             }
15             max = Math.max(max,dp[i]);
16         }
17         return max;
18     }
19 }

Follow-up 是要用O(n*logn)时间.

维护一个list, list.get(i) 是指长度i+1时的subarray 的最后一个数字可以放的最小值。若list.get(2) = 3, 表示长度为2的subarray尾端最小值是3.

举例:假设存在一个序列d[1..9] = 2 1 5 3 6 4 8 9 7. 可以看出来它的LIS长度为5, [1, 3, 4, 8, 9].
下面一步一步试着找出它。
我们定义一个序列B, 然后令 i = 1 to 9 逐个考察这个序列。
此外,我们用一个变量Len来记录现在最长算到多少了
首先, 把d[1]有序地放到B里,令B[1] = 2, 就是说当只有1一个数字2的时候,长度为1的LIS的最小末尾是2. 这时Len=1

然后, 把d[2]有序地放到B里,令B[1] = 1, 就是说长度为1的LIS的最小末尾是1, d[1]=2已经没用了,很容易理解吧。这时Len=1

接着, d[3] = 5, d[3]>B[1], 所以令B[1+1]=B[2]=d[3]=5, 就是说长度为2的LIS的最小末尾是5, 很容易理解吧。这时候B[1..2] = 1, 5. Len=2

再来, d[4] = 3, 它正好加在1,5之间,放在1的位置显然不合适,因为1小于3, 长度为1的LIS最小末尾应该是1, 这样很容易推知, 长度为2的LIS最小末尾是3, 于是可以把5淘汰掉,这时候B[1..2] = 1, 3. Len = 2

继续, d[5] = 6, 它在3后面, 因为B[2] = 3, 而6在3后面,于是很容易可以推知B[3] = 6, 这时B[1..3] = 1, 3, 6. 还是很容易理解吧? Len = 3 了噢。

第6个, d[6] = 4, 你看它在3和6之间,于是我们就可以把6替换掉,得到B[3] = 4. B[1..3] = 1, 3, 4.  Len继续等于3

第7个, d[7] = 8, 它很大,比4大. 于是B[4] = 8. Len变成4了

第8个, d[8] = 9, 得到B[5] = 9. Len继续增大,到5了。

最后一个, d[9] = 7, 它在B[3] = 4和B[4] = 8之间,所以我们知道,最新的B[4] =7, B[1..5] = 1, 3, 4, 7, 9. Len = 5.

于是我们知道了LIS的长度为5.
Note: 这个1,3,4,7,9不是真正的subarray. 它只是存储的对应长度LIS的最小末尾。有了这个末尾,我们就可以一个一个地插入数据。

虽然最后一个d[9] = 7更新进去对于这组数据没有什么意义,但是如果后面再出现两个数字 8 和 9, 那么就可以把8更新到d[5], 9更新到d[6], 得出LIS的长度为6.

然后应该发现一件事情了:在B中插入数据是有序的,而且是进行替换而不需要挪动——也就是说,我们可以使用二分查找,将每一个数字的插入时间优化到O(logN), 于是算法的时间复杂度就降低到了O(NlogN).

Time Complexity: O(nlogn). Space: O(n).

AC Java:

 1 public class Solution {
 2     public int lengthOfLIS(int[] nums) {
 3         if(nums == null || nums.length == 0){
 4             return 0;
 5         }
 6         int max = 1;
 7         int [] minLast = new int[nums.length];
 8         minLast[0] = nums[0];
 9         for(int i = 1; i<nums.length; i++){
10             int pos = bs(minLast, 0, max-1, nums[i]);
11             minLast[pos] = nums[i];
12             if(pos + 1 > max){
13                 max = pos+1;
14             }
15         }
16         return max;
17     }
18
19     private int bs(int [] nums, int l, int r, int key){
20         if(nums[r] < key){
21             return r+1;
22         }
23         while(l < r){
24             int mid = l+(r-l)/2;
25             if(nums[mid] < key){
26                 l = mid+1;
27             }else{
28                 r = mid;
29             }
30         }
31         return l;
32     }
33 }

Reference: http://blog.csdn.net/left_la/article/details/11951085

转载于:https://www.cnblogs.com/Dylan-Java-NYC/p/6405012.html

LeetCode Longest Increasing Subsequence相关推荐

  1. LeetCode Longest Increasing Subsequence(动态规划、二分法)

    问题:求数组的最长上升子序列问题 思路:第一种方法使用动态规划方法,用dp(i)来表示从0到i之间的最长上升子序列的长度.状态转移方程为dp(i)=max{dp(j)+1},其中0<=j< ...

  2. leetcode 300. Longest Increasing Subsequence | 300. 最长递增子序列(动态规划)

    题目 https://leetcode.com/problems/longest-increasing-subsequence/ 题解 难得有官方题解的一道题. 参考:https://leetcode ...

  3. leetcode(300)—— Longest Increasing Subsequence(最长递增子序列)

    参考 Python 解法: 动态规划 -- 最长递增子序列(LIS) 原题位置:Longest Increasing Subsequence | LeetCode OJ 题目的说明: 严格递增: 子序 ...

  4. 【暴力】LeetCode 300. Longest Increasing Subsequence

    LeetCode 300. Longest Increasing Subsequence Solution1:我的答案 暴力搜索,时间复杂度O(n2)O(n2)O(n^2) class Solutio ...

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

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

  6. [Swift]LeetCode673. 最长递增子序列的个数 | Number of Longest Increasing Subsequence

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★ ➤微信公众号:山青咏芝(shanqingyongzhi) ➤博客园地址:山青咏芝(https://www.cnblog ...

  7. HPU第三次积分赛-D:Longest Increasing Subsequence(DP)

    Longest Increasing Subsequence 描述 给出一组长度为n的序列,a1​,a2​,a3​,a4​...an​, 求出这个序列长度为k的严格递增子序列的个数 输入 第一行输入T ...

  8. The Longest Increasing Subsequence (LIS)

    传送门 The task is to find the length of the longest subsequence in a given array of integers such that ...

  9. C++longest increasing subsequence 最长递增子序列的实现之二(附完整源码)

    C++longest increasing subsequence 最长递增子序列的实现 C++longest increasing subsequence 最长递增子序列的的实现完整源码(定义,实现 ...

  10. C++longest increasing subsequence 最长递增子序列的实现之一(附完整源码)

    C++longest increasing subsequence 最长递增子序列的实现 C++longest increasing subsequence 最长递增子序列的的实现完整源码(定义,实现 ...

最新文章

  1. go var type 互转_Go语言学习笔记(第九章) 结构体
  2. 提高CocoaPods速度
  3. python自学教程读书导图-自学Python第一天:起点读书自动领取经验值(附思路讲解)...
  4. eclipse插件 --js
  5. python电子章_Python语言程序设计(电子)答案
  6. 函数mod(a,m)
  7. 《地下城与勇士歼灭贝内尔》回合格斗
  8. Halcon学习笔记:读取多张图片
  9. 服务器系统给U盘盘符,五大步骤解决U盘插入电脑盘符不显示问题
  10. python连乘函数_动态规划之矩阵连乘问题Python实现方法
  11. 青客公寓挂牌房源分城市爬取
  12. ip rule 命令
  13. vscode中用emmet语法a{}*3无法自动换行
  14. pe如何查看计算机用户名,用PE如何查看系统版本
  15. [Pandas] 数据合并 pd.merge
  16. xr企业级应用在哪里_如何在XR中保持私密
  17. NOI系列活动标准竞赛环境(2016年11月08日更新)
  18. 雅诗兰黛中国创新研发中心在上海揭幕;安联贸易任命中国区行政总裁 | 美通企业日报...
  19. 分析2022年国内国际学校ib的分数
  20. 在Google使用Borg进行大规模集群的管理

热门文章

  1. 哪些原因可能导致SQL操作操时呢?
  2. EMNLP'21 | 基于证据检索和图神经验证网络的表格事实验证模型
  3. 【EI 快速检索 | 九月特邀】经济与计算机多主题国际会议
  4. TextCNN可以和对比学习融合吗-SimCSE论文读后感
  5. NLP提效,除了选择合适的模型,就是数据增强了
  6. 【SCIRLab】ACL20 基于图注意力网络的多粒度机器阅读理解文档建模
  7. NLP硬核入门-PointerNet和CopyNet
  8. 【每日算法Day 83】邻居小孩一年级就会的乘法表,你会吗?
  9. python—如何删除(保留)字符串中除字母、数字外的其他元素
  10. 从零实现深度学习框架——理解广播和常见的乘法