Leetcode_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(n2)的方法:
借助一个辅助的数组hash[],hash中记录了以当前元素为最后一个元素的最长序列的值。
遍历给的数组nums[],每次遍历都向左找一个比他小的数,当前的最长序列就是比他小的数的hash值+1。

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int maxLen = 0;
        vector<int> hash(nums.size()+1, 1);
        for(int i = 0; i< nums.size(); i++)
        {
            int j = i -1;
            while(j >= 0)
            {
                if(nums[i] > nums[j])
                    hash[i] = max(hash[j]+1, hash[i]);
                j--;
            }
            maxLen = hash[i]>maxLen?hash[i]:maxLen;
        }
        return maxLen;
    }

};

O(nlogn)解法:
这个解法应该是改自耐心排序。同样借助一个辅助数组sub,这个数组里记录了最长的递增子序列,尽可能保证这里面的元素最小。从头遍历nums,先把nums中第一个元素放到sub中,然后开始遍历数组。如果sub中最后一个元素小于第i个元素,说明sub中有元素应该更新,用折半查找找到第一个比第i个元素小的,替换掉。如果大,那么直接加入到sub的尾部。最后返回sub的长度即可。

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int *sub = new int[nums.size()];
        int length = 0;
        for(int i = 0;i<nums.size();i++)
        {
            if(i == 0) 
            {
                sub[length++] = nums[i];
            }
            else
            {
                if(sub[length-1] < nums.at(i))//直接插入在最后
                {
                    sub[length++] = nums.at(i);
                }
                else if(sub[length-1] > nums.at(i))//折半插入
                {
                    insert(sub, length, nums.at(i));
                }
            }


        }
        return length;
    }


    void insert(int *sub, int &length, int &value)
    {

        int l = 0;
        int h = length - 1;
        while(l<=h)
        {
            int mid = (l+h)/2;
            if(value > sub[mid]) l = mid+1;
            else h = mid -1;
        }
        sub[l] = value;
    }
};

参考:
这里写链接内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值