最长递增子序列的长度

来源:互联网 发布:windows svn服务器 编辑:程序博客网 时间:2024/04/28 14:22

对于一个数字序列,请设计一个复杂度为O(nlogn)的算法,返回该序列的最长上升子序列的长度,这里的子序列定义为这样一个序列U1,U2...,其中Ui < Ui+1,且A[Ui] < A[Ui+1]。

给定一个数字序列A及序列的长度n,请返回最长上升子序列的长度。

测试样例:
[2,1,4,3,1,5,6],7
返回:4

采用两个辅助数组dp[],help[],数组长度均为n.max_length表示最长递增子序列的长度。

dp[i]表示必须以A[i]结尾的最长递增子序列的长度,help[i]表示递增子序列长度为i+1的所有序列中结尾最小的值。其中dp[0]=1,help[0]=A[0].遍历数字序列A,更改dp[],help[]的值,若dp[i]>max_length,更新max_length的值。最后返回max_length。因为help[]是排好序的,所以在更新help[]时查找A[i]的位置时采用二分搜索。遍历数组+二分搜索更新,所以时间复杂度是O(nlogn)
例子:其中红线部分表示更新过程,当插入A[1]=1时,help[0]为2,比1大,所以更新为help[0]=1;当插入A[2]=4时,help[0]=1,比4小,所以更新help[1]=4.重复至遍历数字序列完成。



代码:
class AscentSequence {
public:
    int findLongest(vector<int> A, int n) {
        // write code here
        int dp[MAX_SIZE];
        int help[MAX_SIZE];
        int max_length=0,count=0;
        dp[0]=1;help[0]=A[0];
        for(int i=1;i<n;i++)                             //遍历数字序列
            {
            int right=count,left=0,middle;
            while(left<=right){ //   查找A[i]更新help[]时的位置
                middle=(left+right)/2;
                if(A[i]>=help[middle]){
                    left=middle+1;
                }else{
                    right=middle-1;
                }
            }
            help[left]=A[i];                        //更新help[]的值
            if(left>count)
                count=left;
            dp[i]=left+1;                     //更新dp[]的值
            if(dp[i]>max_length)       //更新最长递增子序列的长度
                max_length=dp[i];
        }
        return max_length;
    }
0 0
原创粉丝点击