LeetCode week 8 : Longest Increasing Subsequence

题目

地址:
https://leetcode.com/problems/longest-increasing-subsequence/description/
类别: Dynamic Programming
难度: Medium
描述:
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?

Credits:
Special thanks to @pbrother for adding this problem and creating all test cases.

分析

题目要求从一个未排序的数组中寻找出最长递增子序列并输出其长度,注意子序列与子串不同,子串要求必须是原数组连续的一段,但子序列可以不连续,只要元素位置是递增的即可。对此问题,我们可将其转化为有向无环图的最长路径问题

解决

初始版(O(n2))

在转化为拓扑图时,每个元素指向其后的大于它的元素组成边集E,则:
状态迁移方程:L(j)(以元素j结尾的最长递增子序列长度) = 1 + max{L(i): (i, j) ∈E}
伪代码:

for j = 1, 2, ... , n:
    L(j) = 1 + max{L(i): (i, j) ∈E}
return max(L(j));

代码实现

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int length[nums.size() + 1];
        length[0] = 1;
        int maxL = 0, maxLj;
        for(int i = 1; i < nums.size(); i++) {
            maxLj = 0;
            for(int j = i - 1; j >= 0; j--) {
                if(nums[j] < nums[i])   maxLj = max(length[j], maxLj);
            }
            length[i] = 1 + maxLj;
        }
        for(int m = 0; m < nums.size(); m++) {
            maxL = max(maxL, length[m]);
        }
        return maxL;
    }
};
进阶版(O(nlogn))

在上面的方法中,我们不难发现在max{L(i): (i, j) ∈E}这一操作中是存在不必要的比较的,事实上我们只需要维护一个数组 min_num 即可,其中的每一个元素min_num[i] = number表示在所有长度为i的最长递增子序列中,number是所有这些序列最后一个元素中最小的。

例如在[0,1,10, 9, 8, x]中, L(10) = 3, L(9) = 3,L(8) = 3,然后在我们求L(x)的时候,我们并不需要将x与前面所有L = 1的都比较, 只需L(8) = 3这一信息即可,因为若x>8, 则只需与8比较即可(其它不一定满足比x小且长度与8相同);若x<8,则需要与L<3的元素比较。(可利用二分查找迅速定位)

又如[5,2,8,6, 3,6,9,7]的维护过程:
min_num[1] = 5→2
min_num[2] = 8→6→3
min_num[3] = 6
min_num[4] = 9→7
其实感觉有一点贪心的味道:每加入一个元素后都维护当前长度为i的递增子序列的最后一个元素最小,这样后面才更有可能产生更长序列。

代码实现

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        vector<int> min_num;    //store the min number of the last number of sequence whose length is i
        for(int i = 0; i < nums.size(); i++) {
            auto it = lower_bound(min_num.begin(), min_num.end(), nums[i]);    //return the position in which the element is no smaller than nums[i];if no such position, return  min_num.end()
            if(it == min_num.end()) min_num.push_back(nums[i]);
            else *it = nums[i];
        }
        return min_num.size();
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值