zoukankan      html  css  js  c++  java
  • 300. 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 is 4.
     
    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?
    

      

    解法:

    解法一:DP(动态规划) Time:O(N^2)

    dp[i]:截止到nums[i],包含nums[i]的最长递增子序列的长度。

    状态转移方程:dp[i] = max(dp[j]+1)  (所有j满足:0~i,nums[j]<nums[i])

    边界:dp[0] = 1(nums[0]只有自己一个数字,最长递增子序列长度,也为 1 )

    代码参考:

     1 class Solution {
     2 public:
     3     //dp[i]:until nums[i](include nums[i]), the length of the longest increasing Subsequence
     4     //dp[i] = max(dp[i], dp[j]+1) (nums[j]<nums[i])
     5     //base:dp[0]=1
     6     int lengthOfLIS(vector<int>& nums) {
     7         int res = 0;
     8         vector<int> dp(nums.size(), 1);
     9         for(int i=0; i<nums.size(); i++) {
    10             for(int j=0; j<i; j++) {
    11                 if(nums[j]<nums[i]) {
    12                     dp[i] = max(dp[i], dp[j]+1);
    13                 }
    14             }
    15             res = max(res, dp[i]);
    16         }
    17         return res;
    18     }
    19 };

    解法二:二分查找(Binary Search)  Time:O(NlogN)

    类似如下游戏:顺序抽取牌,若当前牌<顺序(i:0~res)排列的第 i 堆牌顶top,则将当前牌放入牌堆 i 的牌顶。(上面为牌底,下面为牌顶)

    若直到 第res堆牌的牌顶top,都<当前牌,那么新建一个牌堆,将当前牌推入新牌堆中。

    那么,这一列牌堆有如下特点:

    i:0->res 牌顶为 递增数列

    每一堆牌,从牌顶到牌底(由下到上), 递增

    由于每次新建牌堆,都是,所有牌顶都<当前牌,的情况下,才做的。

    因此最长递增序列长度,则为 牌堆的堆数。 至少所有牌底可以构成一个满足的子序列。

    那么,对于本问题,我们可以模拟该游戏,最终返回堆数res即可。

    这里,在拿到当前牌,去插入牌堆的时候,对递增数列的牌顶(下),可使用二分查找。

    ⚠️ 注意:本题中,[2,2]的结果为 1,则说明只有完全>的数列,才为所求。

    因此在上述游戏中,若找到相同的数字,则仍然合并在同一堆中,不进行新堆的创建,

    因此二分查找,要找到第一个 >=当前牌 的牌堆,进行插入。 

    代码参考:

    class Solution {
    public:
        int lengthOfLIS(vector<int>& nums) {
            int res = 0;
            vector<int> top(nums.size());
            for(int i=0; i<nums.size(); i++) {
                int poker = nums[i];
                int l = 0, r = res, mid;
                while(l<r) {
                    mid = l + (r-l)/2;
                    if(top[mid]>=poker) {
                        r = mid;
                    }else{
                        l = mid+1;
                    }
                }
                if(l==res) res++;
                top[l] = poker;
            }
            return res;
        }
    };
  • 相关阅读:
    Glide只播放一次Gif以及监听播放完成的实现方案
    Android 插件化开发(四):插件化实现方案
    Android 插件化开发(三):资源插件化
    Android 插件化开发(二):加载外部Dex文件
    Android 插件化开发(一):Java 反射技术介绍
    Android框架式编程之架构方案
    Android 项目优化(六):项目开发时优化技巧总结
    Android 项目优化(五):应用启动优化
    Android 项目优化(四):内存优化
    Android 项目优化(三):MultiDex 优化
  • 原文地址:https://www.cnblogs.com/habibah-chang/p/13577819.html
Copyright © 2011-2022 走看看