最长上升子序列

来源:互联网 发布:淘宝店铺免费采集软件 编辑:程序博客网 时间:2024/05/24 01:49

问题描述:

输入一串数字(无序),求最长上升子序列的长度,如输入“3,1,4,2,3,5”,输出4,因为最长上升子序列为“1,2,3,5”。

解法:

  • 动态规划
    用动态规划的思想,假设p[i]表示以nums[i]为末尾的最长上升子序列长度,则有如下最优子结构:
    p[i]={1max0k<i(p[k] | nums[k]<nums[i])+1i=0i=1,2,...,n1
    时间复杂度O(n^2),空间复杂度O(n)。
class Solution {public:    vector<int> p;    int getLength(vector<int>& nums, int k)    {        //求以p[k]为末尾的最长上升子序列长度        if (p[k] != 0) return p[k];        else if (k == 0)            p[0] = 1;        else         {            int maxL = 0;            for (int i = 0; i < k; i++)            {                int temp = getLength(nums, i);                if (nums[k] > nums[i] && temp > maxL)                    maxL = temp;            }            p[k] = maxL + 1;        }        return p[k];    }    int lengthOfLIS(vector<int>& nums) {        p.assign(nums.size(),0);        int maxL = 0;        for (int i = 0; i < nums.size(); i++)        {            int temp = getLength(nums, i);            if (temp > maxL)                maxL = temp;                 }        return maxL;    }};
  • O(nlogn)解法,一个神奇的方法
    同样引入数组p,但p[i]所表示的含义不一样,p[i]指上升子序列长度为i+1时的尾数,举个例子“1,3,1,2,3”,p[0]=1,p[1]=2,p[2]=3,p是个递增的数组。
    从左至右考察数组nums,当考察nums[k]时,从左至右遍历数组p,查找首个p[i]>=nums[k]:

    • 如果没有找到,则数组p在末尾新添成员,值为nums[k],表示多了一个更长的上升子序列,且序列尾数为nums[k];
    • 如果找到首个p[i]>=nums[k],则p[i]要被替换成nums[k],因为只有p[i]变得更小,才能在后面的考察中找到更长的子序列。拿刚刚的例子来说,p[1]也可以为3,为什么后来为2,因为只有这样,p[2]才会被新添进来,成为更长的子序列;

    如果是普通的遍历查找,那时间复杂度还是O(n^2),但如果是二分查找,时间复杂度就是O(nlogn)。

class Solution {public:    int binarySearch(vector<int>& p, int s)    {        //从左至右遍历数组p,查找首个p[i]>=s的下标        int l = 0, r = p.size() - 1;        while (l <= r)        {            int mid = (l + r) / 2;            if (p[mid] >= s) r = mid - 1;            else l = mid + 1;        }        return r + 1;    }//如果没有找到返回接下来要放的位置    int lengthOfLIS(vector<int>& nums) {        vector<int> p;        for (int i = 0; i < nums.size(); i++)        {            int temp = binarySearch(p, nums[i]);            if (temp == p.size())                p.push_back(nums[i]);            else p[temp] = nums[i];        }        return p.size();    }};
0 0