• Leetcode: 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(n2) complexity.
    
    Follow up: Could you improve it to O(n log n) time complexity?

    讲解一: 用一个数组来存 the smallest tail of all increasing subsequences with length i+1 in tails[i].

    For example, say we have nums = [4,5,6,3], then all the available increasing subsequences are:

    len = 1   :      [4], [5], [6], [3]   => tails[0] = 3
    len = 2   :      [4, 5], [5, 6]       => tails[1] = 5
    len = 3   :      [4, 5, 6]            => tails[2] = 6

    We can easily prove that tails is a increasing array. Therefore it is possible to do a binary search in tails array to find the one needs update.

    Each time we only do one of the two:

    (1) if x is larger than all tails, append it, increase the size by 1
    (2) if tails[i-1] < x <= tails[i], update tails[i]
    

    Doing so will maintain the tails invariant. The the final answer is just the size.

    讲解二:

    1,3,5,2,8,4,6这个例子中,当到6时,我们一共可以有四种
    (1)不同长度
    (2)且保证该升序序列在同长度升序序列中末尾最小
    的升序序列

    1
    1,2
    1,3,4
    1,3,5,6

    这些序列都是未来有可能成为最长序列的候选人。这样,每来一个新的数,我们便按照以下规则更新这些序列

    • 如果nums[i]比所有序列的末尾都大,或等于最大末尾,说明有一个新的不同长度序列产生,我们把最长的序列复制一个,并加上这个nums[i]

    • 如果在中间,则更新那个末尾数字刚刚大于等于自己的那个序列,说明那个长度的序列可以更新了。

    比如这时,如果再来一个9,那就是第一种情况,更新序列为

    1
    1,2
    1,3,4
    1,3,5,6
    1,3,5,6,9
    

    如果再来一个3,那就是第二种情况,更新序列为

    1
    1,2
    1,3,3
    1,3,5,6
    

    如果再来一个0,那就是第二种情况,更新序列为

    0
    1,2
    1,3,3
    1,3,5,6
    

    前两种都很好处理,O(1)就能解决,主要是第三种情况,实际上我们观察直到6之前这四个不同长度的升序序列,他们末尾是递增的,所以可以用二分搜索来找到适合的更新位置。

     1 public class Solution {
     2     public int lengthOfLIS(int[] nums) {
     3         if (nums==null || nums.length==0) return 0;
     4         ArrayList<Integer> list = new ArrayList<Integer>();
     5         for (int num : nums) {
     6             if (list.size()==0 || num>list.get(list.size()-1))
     7                 list.add(num);
     8             else {
     9                 update(list, num);
    10             }
    11         }
    12         return list.size();
    13     }
    14     
    15     public void update(ArrayList<Integer> list, int num) {
    16         int l=0, r=list.size()-1;
    17         while (l <= r) {
    18             int m = l + (r-l)/2;
    19             if (list.get(m) == num) return;
    20             else if (list.get(m) > num) {
    21                 r = m-1;
    22             }
    23             else l = m+1;
    24         }
    25         list.set(l, num);
    26     }
    27 }

    时间O(N^2), 空间O(N)

    DP

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

     follow up:怎么求真正的Longest Increasing Subsequence呢?

    我现在的想法是在DP基础上,另外构建一个ArrayList<ArrayList<Integer>>存以nums[i]为结尾的LIS

  • 相关阅读:
    原创 [免费解答]第12届中国大学生数学竞赛非数学类预赛试题
    原创 [免费解答]第12届中国大学生数学竞赛数学B类预赛试题
    原创 [免费解答]第12届中国大学生数学竞赛数学A类预赛试题
    2017年浙江省高等数学(微积分)竞赛工科类试题
    2016年浙江省高等数学(微积分)竞赛工科类试题
    原创 [免费解答]2019年浙江省高等数学(微积分)竞赛工科类试题
    大学生数学竞赛及数学分析高等代数考研试题参考解答. 更多请微信搜一搜: 跟锦数学
    [考研试题汇总]广西民族大学数学分析高等代数考研试题
    原创 [免费解答]2020年第17届江苏省高等数学竞赛本科1级A试题
    [数学考研竞赛讲座]微分中值定理与积分中值定理
  • 原文地址:https://www.cnblogs.com/EdwardLiu/p/5084553.html
Copyright © 2020-2023  润新知