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

来源:互联网 发布:vscode markdown html 编辑:程序博客网 时间:2024/05/21 20:22

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)。



0 0