最长上升子序列

来源:互联网 发布:学c语言用什么编译器 编辑:程序博客网 时间:2024/05/08 04:37
Longest Increasing Subsequence
https://leetcode.com/problems/longest-increasing-subsequence/
求最长上升子序列,这是一道很经典的题,这道题有两种解法。一种是O(n2)的时间复杂度。用一个数组res记录从第一个节点开始到第i个节点的最长上升子序列。对于每一个点,我们从头开始遍历,如果碰到有num[j]<num[i]那么res[i]=res[j]+1,那么对于一个节点来说,res[i]=max(res[j])+1。
class Solution {public:    int lengthOfLIS(vector<int>& nums) {        if(nums.size()==0||nums.size()==1) return nums.size();        vector<int> res(nums.size(),0);        res[0]=1;        for(int i=1;i<nums.size();i++){            int ans=res[i];            for(int j=0;j<i;j++){                if(nums[i]>nums[j]&&res[j]>ans) ans=res[j];            }            res[i]=ans+1;        }        int ans=res[0];        for(int i=1;i<nums.size();i++){            if(res[i]>ans) ans=res[i];        }        return ans;    }};
另外一种方法是使用二分搜索,使用一个数组res记录当前有i个数字的升序序列的最后一个数的最小值。因此,当遍历数组时:
如果nums[i]>res[k],则res[k+1]=nums[i]
如果nums[i]<res[k],则对res从0到k-1进行二分搜索查找出j使res[j-1]<nums[i]<res[j],那么我们就找到了在j个数字的升序序列中最后一个数最小的数了。res[j]=nums[i]
如果nums[i]=res[k]不做任何反应。
class Solution {public:    int lengthOfLIS(vector<int>& nums) {        //O(nlogn)        if(nums.size()==0||nums.size()==1) return nums.size();        vector<int> res(nums.size(),0);//记录i个上升序列的最小值        res[0]=nums[0];        int len=0;        for(int i=1;i<nums.size();i++){            if(nums[i]<res[0]) res[0]=nums[i];            else if(nums[i]>res[len]){                res[++len]=nums[i];            }            else{                res[biSearch(res,0,len,nums[i])]=nums[i];            }        }        return len+1;    }        int biSearch(vector<int> &res,int start,int end,int num){        int s=start;        int e=end;        while(s<=e){            int mid=s+(e-s)/2;            if(res[mid]==num) return mid;            else if(res[mid]>num) e=mid-1;            else if(res[mid]<num) s=mid+1;        }        return s;    }};



0 0
原创粉丝点击