300. Longest Increasing Subsequence

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?

思路1:DP

令dp[i]表示nums[i]递增序列的最大长度,dp的初始值为1
然后遍历数组,如果num[i]>nums[j]

d p [ i ] = M a t h . m a x ( d p [ i ] , d p [ j ] + 1 ) dp[i]=Math.max(dp[i],dp[j]+1) dp[i]=Math.max(dp[i],dp[j]+1)

然后取dp的最大值即可

public int lengthOfLIS(int[] nums) {
        int[] dp = new int[nums.length];
        int maxLen=1;
        Arrays.fill(dp, 1);
        for (int i = 1; i < nums.length; i++) {
            for (int j = 0; j < i; j++) {
                if (nums[i] > nums[j]) {
                    dp[i] = Math.max(dp[i], dp[j] + 1);
                    maxLen=Math.max(dp[i],maxLen);
                }
            }
        }
        return maxLen;
    }

思路2:二分法

这种方法的解题步骤是:
-将第1个数字加入解集;
-依次读取后面的数字,如果此数字比解集中最后一个数字大,则将此数字追加到解集后,否则,用这个数字替换解集中第一个比此数字大的数,解集是有序的,因此查找可以用二分法,复杂度O(log n);
-最后的答案是解集的长度(而解集中保存的并不一定是合法解)。
举个栗子,输入为[1,4,6,2,3,5]:
-解集初始化为[1];
-读到4,将其追加到解集中,解集变为[1,4];
-读到6,将其追加到解集中,解集变为[1,4,6];
-读到2,用其替换解集中的4,解集变为[1,2,6],注意此时解集不是一个合法解,因为2是在6后出现的,但是解集的长度始终标识着当前最长序列的长度;
-读到3,用其替换解集中的6,解集变为[1,2,3];
-读到5,将其追加到解集中,解集变为[1,2,3,5],得到答案为解集长度4。

public int lengthOfLIS(int[] nums) {
        if (nums.length <= 1) return nums.length;
        List<Integer> result=new ArrayList<>();
        result.add(nums[0]);
        int curLen=1;
        for(int i=1;i<nums.length;i++){
            if(nums[i]>result.get(curLen-1)){
                result.add(nums[i]);
                curLen++;
            }else {
                result.set(lengthOfLIS(result,nums[i]),nums[i]);
            }
        }
        return result.size();
    }
    private int lengthOfLIS(List<Integer> l,int target){
        int p=0,q=l.size()-1;
        while (p<=q){
            int m=(p+q)>>1;
            if(l.get(m)==target){
                return m;
            }else if(l.get(m)>target){
                q=m-1;
            }else{
                p=m+1;
            }
        }
        return p;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值