300. Longest Increasing Subsequence

题目:

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?


题意:

给定一个无序的整数数组,找到最长的递增子序列。算法应该在O(n^2)的时间复杂度内。返回的值只是最长子序列的长度,需要注意的是最长子序列可能不止一种组合。

Follow up:

是否能改进O(n2)的时间复杂度到O(nlogn)时间复杂度。


思路一:

使用动态规划,使用数组res[i]记录到下标i时最长的上升序列,时间复杂度为O(n2),将num数组中的每个值与之前的所有值进行对比,如果比它小的值,在小的值最长序列上加1;

nums109253710118
res11122344

代码:java版:33ms

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

思路二:

使用二分搜索替代上面的内循环,将时间复杂度由O(n2)提升到O(nlogn),使用dp数组记录当前最长上升序列的值。注意Arrays.binarySearch函数的返回值特点。

起点

Len

X值

Dp数组值

Arrays.binarySearch结果值

0

0

10

0 0 0 0 0 0 0 0

-1

0

1

9

10 0 0 0 0 0 0 0

-1

0

1

2

9 0 0 0 0 0 0 0

-1

0

1

5

2 0 0 0 0 0 0 0

-2

0

2

3

2 5 0 0 0 0 0 0

-2

0

2

7

2 3 0 0 0 0 0 0

-3

0

3

101

2 3 7 0 0 0 0 0

-4

0

4

18

2 3 7 101 0 0 0 0

-4

代码:java版:2ms

public class Solution {
    public int lengthOfLIS(int[] nums) {
        int[] dp = new int[nums.length];
        int len = 0;
        
        for (int x : nums) {
            int i = Arrays.binarySearch(dp, 0, len, x);
            if (i<0)
                i = -(i + 1);
            dp[i] = x;
            if (i == len)
                len++;
        }
        return len;
    }
}

思路三:

利用std::lower_bound函数获取到序列应该插入的下标值,如果返回的下标值处于res的末尾,则说明比res数组尾数大,是递增,则将该数添加到res数组之后,如果小于res数组末尾值,则覆盖更新该处的值。

代码:7ms

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        vector<int> res;
        for(int i=0; i<nums.size(); i++) {
            auto it = std::lower_bound(res.begin(), res.end(), nums[i]);
            if(it==res.end()) res.push_back(nums[i]);
            else *it = nums[i];
        }
        return res.size();
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值