编程之美读书笔记之2.16求数组中最长递增子序列

1.自己的解题思路是用动态规划的思想,从后往前遍历

定义f(x)表示以a[x]为最小元素的最长递增子序列的长度;则f(n-1)=1;

f(i) = 1,如果对于任意的j>i有 a[i]>=a[j];

f(i)=1+f(j),其中j满足a[i]<a[j];,且是满足j>i所有j中最小的一个。

实现代码如下:

int Solute1(vector<int> &Vec)
{
    int maxLength = 1;
    int *tempArrayp = new int[Vec.size()]();


    for(int i=Vec.size()-1 ; i>=0 ; i--){
        tempArrayp[i] = 1;
        for(int j=i+1 ; j<Vec.size() ; j++){
            if(Vec[i] < Vec[j]){
                tempArrayp[i] = tempArrayp[j] + 1;
                if(tempArrayp[i] > maxLength){
                    maxLength = tempArrayp[i];
                }
                break;
            }
        }
    }
    delete []tempArrayp;
    return maxLength;
}

2.书中的解法一是从前往后遍历,定义f(n)表示以a[n]为最大元素的最长递增子序列的长度。

f(n+1) = max{1,f(i)+1},其中a[i]<a[n+1],对于任意的i≤n;

实现代码如下:

int Solute2(vector<int> &Vec)
{
    int maxLength = 1;
    int *tempArrayp = new int[Vec.size()]();

    for(int i=0 ; i<Vec.size() ; i++){
        tempArrayp[i] = 1;
        for(int j=i-1 ; j>=0 ; j--){
            if(Vec[i]>Vec[j] && tempArrayp[i]<tempArrayp[j]+1){
                tempArrayp[i] = tempArrayp[j] + 1;
                if(tempArrayp[i] > maxLength){
                    maxLength = tempArrayp[i];
                }
                //break;
            }
        }
    }
    delete []tempArrayp;
    return maxLength;
}

3.书中的改进算法,没具体看实现,只是看了下思路,可能略有不同。

改进Solute2中第二个for循环,增加maxV数组,记录满足长度为i的子序列的最大元素的最小值。


int Solute3(vector<int> &Vec)
{
    int *tempArrayp = new int[Vec.size()]();
    vector<int> maxV;

    maxV.push_back(0);

    for(int i=0 ; i<Vec.size() ; i++){
        tempArrayp[i] = 1;
        for(int j=maxV.size()-1 ; j>=0 ; j--){
            if(Vec[i]>Vec[maxV[j]]){
                tempArrayp[i] = tempArrayp[maxV[j]] + 1;
                if(tempArrayp[i]>maxV.size()-1){
                    maxV.push_back(i);
                }
            }

        }
    }
    delete []tempArrayp;
    return maxV.size();

}

三个算法的复杂度都是O(n^2),方法一和方法三比方法二查找次数少,方法三可以进一步用二分思想改进,复杂度达到O(nlgn)。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值