300. Longest Increasing Subsequence

来源:互联网 发布:淘宝店能注销吗 编辑:程序博客网 时间:2024/05/16 05:25

1.Question

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?

2.Code

codeA

class Solution {public:    int lengthOfLIS(vector<int>& nums) {        int size = nums.size();        int res = 0;        for(int i = 0; i < size; i++)        {            int p1 = nums[i];            int p2 = nums[i];            int count = 1;            for(int j = i+1; j < size; j++)            {                if(nums[j] > p1)                {                    if(nums[j] <= p2) p2 = nums[j];                    else                    {                        p1 = p2;                        p2 = nums[j];                        count++;                    }                }            }            res = max(res, count);        }        return res;    }};

codeB

class Solution {public:    int lengthOfLIS(vector<int>& nums) {        int size = nums.size();        if(size == 0) return 0;        int label = 0;        vector<int> minMax(size);        minMax[0] = nums[0];        for(int i = 1; i < size; i++)        {            int num = nums[i];            if(num > minMax[label])            {                minMax[++label] = num;            }            else            {                int left = 0;                int right = label;                int mid;                while(left < right)                {                    mid = left + 0.5 * (right - left);                    if(num == minMax[mid]) break;                    else if(num > minMax[mid]) left = mid + 1;                    else right = mid - 1;                }                if(num > minMax[left]) minMax[left+1] = num;                else minMax[left] = num;            }        }        return label + 1;    }};

3.Note


a.  codeA也是一种解题思路,复杂度O(n2) 。遍历n次(i = 1:n),每一次都是以第 i 个数字为起始,搜索到最后一个数字。然后用p1记录当前第二大的数字,p2记录当前第一大的数字,如果nums[j]比p1大,且比p2大,则count++,并且更新p1和p2,若比p2小,则只需用nums[j]替换掉p2。这里也类似于动态规划的状态,p1,p2用于记录当前状态的值。

b. codeB的思路,基于用 lis[i] 来记录当前最长序列长度 的思路,同样是O(n2) 。遍历n次(i = 1:n),每一次都是以第1个数字为起始,搜索到第 i 个数字。在j从1到i搜索过程中,对于list[i],若nums[j] < nums[i],list[i] = max(list[i], list[j]+1) 。

这时候,假设我们用一个数组minMax来记录序列的末尾数字。什么意思呢?比如minMax[label],则是指,长度为(label+1) (label 从0 开始) 的序列的末尾数字,它是保证该长度下的序列,在末尾最小的数字。这时,我们可以发现,如果a>b, 一定有 minMax[a] > minMax[b] (性质1)。那么minMax数组的真实长度就是lis了。我们在遍历一次nums的时候,如果nums[i]大于minMax[label]则说明最长序列可以更长,则更新minMax[l++label],否则,nums[i]一定会小于minMax数组中的某一个值,它会成为该值对应的长度下的序列的最新的末尾最小数字。而我们已知 minMax数组有 性质1,即有序数列,则可以通过二分查找法加速搜索。所以复杂度就是O(nlogn)了。

0 0
原创粉丝点击