Leetcode:300. 最长上升子序列

Leetcode:300.最长上升子序列

题目描述

给定一个无序的整数数组,找到其中最长上升子序列的长度。

示例:

输入: [10,9,2,5,3,7,101,18]
输出: 4 
解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。

说明:

可能会有多种最长上升子序列的组合,你只需要输出对应的长度即可。
你算法的时间复杂度应该为 O(n2) 。
进阶: 你能将算法的时间复杂度降低到 O(n log n) 吗?

思路

思路1 动态规划

维持每个数字对应的上升子序列长度,然后根据状态转移方程$dp[i] = max(dp[j] + 1) j\in(nums[j] < nums[i] && j < i>>)$

思路2 贪心+二分搜索

使用一个数组保存从小到大的数字,在相同的上升子序列长度只保留一个值(最小值),然后每个数字进来二分查找找到合适的位置。

代码

代码1

class Solution {
    public int lengthOfLIS(int[] nums) {
        if (nums == null || nums.length == 0){
            return 0;
        }
        int result = 0;
        int dps[] = new int[nums.length];
        for(int i = 1; i < nums.length; i++){
            for(int j = 0; j < i; j++){
                if (nums[i] > nums[j]){
                    dps[i] = Math.max(dps[j] + 1, dps[i]);
                    if (result < dps[i]){
                        result = dps[i];
                    }
                }
            }
        }
        return result + 1;
    }
}

代码2

class Solution {
    public int lengthOfLIS(int[] nums) {
        if (nums == null || nums.length == 0){
            return 0;
        }
        int n = nums.length;
        int[] dps = new int[n + 1];
        int len = 1;
        dps[1] = nums[0];
        for(int i = 1; i < n; i++){
            if (nums[i] > dps[len]){
                dps[++len] = nums[i];
                continue;
            }
            int left  = 1, right = len;
            int origin = 0;
            while(left <= right){
                int mid = (left + right) / 2;
                if (dps[mid] < nums[i]){
                    origin = mid;
                    left = mid + 1;
                }else{
                    right = mid - 1;
                }
            }
            dps[origin + 1] = nums[i];
        }
        return len;
    } 
}

复杂度分析

思路1时间复杂度

$O(n^2)$

思路1空间复杂度

$O(n)$

思路2时间复杂度

$O(nlogn)$

思路2空间复杂度

$O(n)$


文章作者: 小风雷
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 小风雷 !
评论
 上一篇
Leetcode:322. 零钱兑换 Leetcode:322. 零钱兑换
Leetcode: 322.零钱兑换题目描述给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。 示例 1:输入: coins
2020-04-25
下一篇 
Leetcode:279. 完全平方数 Leetcode:279. 完全平方数
Leetcode:279. 完全平方数题目描述给定正整数 n,找到若干个完全平方数(比如 1, 4, 9, 16, ...)使得它们的和等于 n。你需要让组成和的完全平方数的个数最少。 示例 1:输入: n = 12 输出: 3 解释:
2020-04-23
  目录