Longest Increasing Subsequence

原创 2015年11月20日 11:45:50

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?

思路: 题目的意思是求数组中递增序列的最大长度,序列是可以不连续的。用f(i)表示第0~i个数中递增序列的最大长度。 对于每一个nums[i]要求f(i) 的话,需要找出0~(i-1) 中所有小于nums[i] 的数nums[j],其中 0 <= j <=(i-1),记录下最大的f(j) ,记为max ,那么f(i)=max+1 ,否则找不到比nums[i]还要小的数,f(i)=1,并在整个遍历数组的过程中记录递增序列的最大长度res。
对于数组nums = [10, 9, 2, 5, 3, 7, 101, 18] ,res表示所要求的最大递增序列的长度。

  1. 初始值 f(0) =1 ,更新res=1
  2. 对于 i =1 , nums[1]=9 , 在1之前没有小于nums [i] 的数 ,所以f(1)=1, res=1
  3. 对于i=2 ,nums[2]=2, 在2之前没有小于nums[i]的数,所以f(2)=1,res=1
  4. 对于i=3 ,nums[3]=5 ,在3之前小于5的数有2 ,max=f(2)=1,所以f(5)=max+1=2, 此时更新res=2
  5. 对于i=4,nums[4]=3 ,在4之前小于3的数有 2,f(3)=f(2)+1=2, 此时res=2
  6. 对于i=5,nums[5]=7,在 5之前小于7的数有2,3,5 ,而f(2)=1, f(3)=2,f(5)=2 , max是f(2)、f(3)和f(5)中最大的一个,max=2,则f(7)=3,此时更新res=3
  7. 对于i=6,nums[i]=101, 在6之前小于101的有f(0),f(1),f(2),f(3),f(4),f(5),它们之中最大的为3,则max=3,所以f(6)=max+1=4,此时更新res=4
  8. 同理,对于i=7 ,有f(7)=4 ,此时res=4

最后最长递增子序列的长度为res=4

算法如下,但是时间复杂度为o(n^2)。

public class Solution {
    public int lengthOfLIS(int[] nums) {
        int res=0;
        int n=nums.length;
        if(n==0) return 0;
        int[] f=new int[n];
        f[0]=1; res=1;
        for(int i=1;i<n;i++)
        {
            int max=Integer.MIN_VALUE;
            for(int j=i-1;j>=0;j--)
              {
                  if(nums[j]<nums[i])
                    max= max > f[j] ? max : f[j];
              }

                f[i]=( max!=Integer.MIN_VALUE ? max+1 : 1);
                res= res > f[i] ? res : f[i] ;
        }

        return res;
    }
}

改进: 想到是查找算法,上述算法所用的是线性查找,比线性查找更加快的是二分查找算法,但是二分查找算法需要每次可以折半,如果可以查找一个有序的序列那就好了。 我们可以用一个数组len来记录对应长度的序列末尾最小的一个数字,这话说起来比较绕口,举个例子
比如len[3] 表示 长度为3的序列中末尾数字中最小的一个数

有如下序列:

3,1,2,6,4,-1,5,8,9
比如在数字5之前,长度为3的递增序列有 1,2,6 和1,2,4 这两个序列的末尾数字分别为6和4,其中4比6小,所以记录长度为3的递增序列的末尾数字为len[3]=4

容易证明当   i <j 的时候有 len[i] < len[j] ,  假设j=i+k , i<j =i+k 
len[i]=m ,len[i+k] =n 如果m>n 那就说明长度为i的序列的最后一个数字大于长度为i+k的最后一个数字,这个不合理的,m在n的后面,到n的时候序列的长度已经可以是i+k了,到m的时候长度肯定不止i+k了,所以len[i]=m是不合理的,所以一定有 i<j ,就有len[i] < len[j]

这样,可以在遍历到 数组之下标为s的时候 ,在len[1]至 len[s]中找到一个比nums[s]还要小的数r,r对应的长度为索引 idx,更新f(s)=idx+1 ,如果len[idx+1]大于nums[s],更新len[idx+1]=nums[s]

public class Solution {
    public int lengthOfLIS(int[] nums) {
        int res=0;
         int n=nums.length;
         if(n==0) return 0;
         int[] f=new int[n];
         f[0]=1;
         int[] len=new int[n+1];
         len[1]=nums[0];
         for(int i=1;i<n;i++)
         {
             //二分查找len中小于nums[i]的数
             int j=i;
             while(j>=1 && len[j]==0)
                 j--;
             int right=j;
             int left=1;
             while(left<=right)
             {
                 int mid=left+(right-left)/2;
                 if(len[mid]>=nums[i])
                 {
                     right=mid-1;
                 }else 
                     left=mid+1;

             }
              if(right<left) 
                  f[i]= right+1;
             if(len[f[i]]!=0)
               len[f[i]]= len[f[i]] < nums[i] ? len[f[i]] : nums[i];
             else len[f[i]]=nums[i]; 
             res=res > f[i] ? res : f[i];

         }
         return res!=0 ? res : 1;
    }
}

【LEETCODE】300-Longest Increasing Subsequence [Python]

Given an unsorted array of integers, find the length of longest increasing subsequence. For example...
  • aliceyangxi1987
  • aliceyangxi1987
  • 2016年01月07日 20:36
  • 867

673. Number of Longest Increasing Subsequence

Given an unsorted array of integers, find the number of longest increasing subsequence. Example 1...
  • zjucor
  • zjucor
  • 2017年09月10日 11:03
  • 625

LWC 49:674. Longest Continuous Increasing Subsequence

LWC 49:674. Longest Continuous Increasing Subsequence 详细代码可以fork下Github上leetcode项目,不定期更新。 从今天开始改变下...
  • u014688145
  • u014688145
  • 2017年09月10日 14:03
  • 469

LWC 49:673. Number of Longest Increasing Subsequence

LWC 49:673. Number of Longest Increasing Subsequence传送门:673. Number of Longest Increasing Subsequenc...
  • u014688145
  • u014688145
  • 2017年09月10日 17:56
  • 946

LeetCode 300. Longest Increasing Subsequence 解题报告

300. Longest Increasing Subsequence My Submissions Question Total Accepted: 17302 Total S...
  • bruce128
  • bruce128
  • 2016年02月16日 19:35
  • 3356

673. Number of Longest Increasing Subsequence 最长递增子序列的个数

Given an unsorted array of integers, find the number of longest increasing subsequence. Example 1: ...
  • m0_37693059
  • m0_37693059
  • 2017年09月22日 10:55
  • 273

674. Longest Continuous Increasing Subsequence

Given an unsorted array of integers, find the length of longest continuous increasing subsequence...
  • mml1106
  • mml1106
  • 2017年09月10日 14:56
  • 163

Leetcode 300 Longest Increasing Subsequence(Python)

题目大意确定一个未排序数组中最大上升子序列的长度算法很简单,没啥可说的。 就是维护一个数组A 如果当前数num比数组A最后一个元素大,那么依旧构成一个上升序列,将其放到数组A最后。 否则,二分查找数...
  • wds2006sdo
  • wds2006sdo
  • 2016年07月19日 01:57
  • 2872

Longest Increasing Subsequence (LIS) 的java实现

最长递增子序列 Longest Increasing Subsequence (LIS) 的java实现
  • zhangmicky
  • zhangmicky
  • 2011年02月17日 04:33
  • 1529

leetcode_Longest Increasing Subsequence

描述: Given an unsorted array of integers, find the length of longest increasing subsequence. For ...
  • dfb198998
  • dfb198998
  • 2015年11月27日 08:53
  • 353
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Longest Increasing Subsequence
举报原因:
原因补充:

(最多只允许输入30个字)