zoukankan      html  css  js  c++  java
  • 65.Longest Increasing Subsequence(最长增长子序列)

    Level:

      Medium

    题目描述:

    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 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[ i ]表示以第i个元素结尾的最长递增子序列的长度,那么状态转移方程就为 if(nums[ j ]<nums[ i ]) dp[ i ]=max(dp[ j ]+1,dp[ i ]);这个递推方程的意思是,在求以nums[ i ]为末尾元素的最长递增子序列时,找到所有序号在 i 之前的且小于nums[ i ]的元素nums[ j ],即 j < i,且 nums[ j ]<nums[ i ]。如果这样的元素存在,那么对于所有的nums[ j ]都有一个以nums[ i ]结尾的最长递增子序列 ,我们将其中的最长序列选出来就是,以nums[ i ]结尾的最长递增子序列长度,如果这样的元素不存在,那么我们以nums[ i ]自身组成一个以它为结尾的递增子序列。算法的时间复杂度为O(n)。

    ​  思路二:设计一个容器来存放最长上升子序列,先将nums[0]放入,遍历nums,如果访问到的元素大于,容器尾部的元素,直接加到尾部,如果小于,则使用二分查找找到第一个比其大的元素,将其替换。最终访问完成时,容器中就是最长上升子序列
    假设要寻找最长上升子序列的序列是a[n],然后寻找到的递增子序列放入到数组b中。

    ​  (1)当遍历到数组a的第一个元素的时候,就将这个元素放入到b数组中,以后遍历到的元素都和已经放入到b数组中的元素进行比较;

    ​  (2)如果比b数组中的每个元素都大,则将该元素插入到b数组的最后一个元素,并且b数组的长度要加1;

    ​  (3)如果比b数组中最后一个元素小,就要运用二分法进行查找,查找出第一个比该元素大的最小的元素,然后将其替换。

    ​  在这个过程中,只重复执行这两步就可以了,最后b数组的长度就是最长的上升子序列长度。例如:如该数列为:

    ​  5 9 4 1 3 7 6 7

    ​  那么:

    ​  5 //加入
    ​  5 9 //加入
    ​  4 9 //用4代替了5
    ​  1 9 //用1代替4
    ​  1 3 //用3代替9
    ​  1 3 7 //加入
    ​  1 3 6 //用6代替7
    ​  1 3 6 7 //加入

    ​  最后b中元素的个数就是最长递增子序列的大小,即4。

    ​  要注意的是最后数组里的元素并不就一定是所求的序列,例如如果输入 2 5 1那么最后得到的数组应该是 1 5而实际上要求的序列是 2 5

    代码:

    思路一

    public class Solution{
        public int lengthOfLIS(int []nums){
            if(nums==null||nums.length==0)
                return 0;
            int []dp=new int [nums.length];
            dp[0]=1; //表示以nums[0]为结尾的最长递增子序列
            int res=1;
            for(int i=1;i<nums.length;i++){
                dp[i]=1;
                for(int j=0;j<i;j++){
                    if(nums[j]<nums[i]){
                        dp[i]=Math.max(dp[j]+1,dp[i]);
                        res=Math.max(res,dp[i]);
                    }
                }
            }
            return res;
        }
    }
    

    思路二

    public class Solution{
        public int lengthOfLIS(int []nums){
            if(nums==null||nums.length==0)
                return 0;
            int []temp=new int [nums.length];
            int size=0;
            temp[size]=nums[0];
            for(int i=1;i<nums.length;i++){
                if(nums[i]>temp[size]){
                    size++;
                    temp[size]=nums[i];
                }else{
                    int t=search(0,size,temp,nums[i]); //找到第一个大于nums[i]的数
                    temp[t]=nums[i];
                }
            }
            return size+1;
        }
        public int search(int start,int end,int []temp,int k){//二分查找第一个大于k的值
            while(start<=end){
                int mid=(start+end)/2;
                if(temp[mid]<k){
                    start=mid+1;
                }else{
                    end=mid-1;
                }
            }
            return start;
        }
    }
    
  • 相关阅读:
    爬虫简介
    MongoDb安装pymongo和mongoengine使用
    简单使用WebSocket实现聊天室
    DBUtils
    FLASK 的Session和MoudelForm插件
    第十一篇 CBV和闪现
    HDOJ 4699 Editor 对顶栈
    [NOI1999]内存分配
    横截面图
    STL List Set
  • 原文地址:https://www.cnblogs.com/yjxyy/p/11090573.html
Copyright © 2011-2022 走看看