1.暴力求解法,时间复杂度为O(2^n)
- // 最长子序列问题求解
- // 比如序列:3,7,4,8,5,9
- // 最长子序列的长度为:4
- // 子序列为: 3,4,5,9.
-
-
- #include"iostream"
- using namespace std;
- // 求最大值函数
- unsigned int maxnum(unsigned int a,unsigned int b)
- {
- return a>b ? a:b;
- }
- // 暴力求解
- // 对当前位置i求解最大子序列
- unsigned int relongsequence(unsigned int *array,int i,int size)
- {
- // 默认长度为1
- unsigned int maxlong=1;
- // 对i位置的元素进行比较
- for(int j=i+1;j<size;j++)
- {
- // i位置小于j位置的值
- if(*(array+i)<*(array+j))
- {
- // 可以构成序列,继续对j位置进行求解出子序列的值,如果j位置的值比maxlong大,那就是计算出来的新maxlong值,否则就是maxlong.
-
- maxlong=maxnum(relongsequence(array,j,size)+1,maxlong);
-
- }
- }
- // 返回i位置最大序列
- return maxlong;
- }
- unsigned int Maxlongsquence(unsigned int *array,int size)
- {
- // 默认最大子序列长度为0
- unsigned int maxlongsize=0;
- // 依次计算i到size-1
- for(int i=0;i<size;i++)
- {
- // 如果计算出来的子序列比maxlongsize大,就是计算出来的子序列的值,否则就是maxlongsize的值
- maxlongsize = maxnum(relongsequence(array,i,size),maxlongsize);
- }
- // 返回最大子序列
- return maxlongsize;
- }
-
- int main(int argc,char *argv[])
- {
- // 定义一个序列
- unsigned int array[6]={3,7,4,8,5,9};
-
- unsigned int longsizesequence=0;
- // 开始计算子序列
- longsizesequence = Maxlongsquence(array,6);
- // 输出最大子序列的值
- cout<<longsizesequence<<endl;
-
- return 0;
- }
2.动态规划算法求解,时间复杂度为O(n^2)
- // 最长子序列问题求解
- // 比如序列:3,7,4,8,5,9
- // 最长子序列的长度为:4
- // 子序列为: 3,4,5,9.
-
-
- #include"iostream"
- using namespace std;
- // 求最大值函数
- unsigned int maxnum(unsigned int a,unsigned int b)
- {
- return a>b ? a:b;
- }
- // 动态规划求解
- // 对当前位置i求解最大子序列
- unsigned int relongsequence(unsigned int *array,unsigned int *memo,int i,int size)
- {
- // 如果i位置的最长子序列已经计算出来了
- if(memo[i]!=0)
- {
- // 直接返回i位置的最长子序列
- return memo[i];
- }
-
- // 默认长度为1
- unsigned int maxlong=1;
- // 对i位置的元素进行比较
- for(int j=i+1;j<size;j++)
- {
- // i位置小于j位置的值
- if(*(array+i)<*(array+j))
- {
- // 可以构成序列,继续对j位置进行求解出子序列的值,如果j位置的值比maxlong大,那就是计算出来的新maxlong值,否则就是maxlong.
-
- maxlong=maxnum(relongsequence(array,memo,j,size)+1,maxlong);
-
-
- }
- }
- // 保存i位置的最长子序列
- memo[i]=maxlong;
- // 返回i位置最大序列
- return maxlong;
- }
- unsigned int Maxlongsquence(unsigned int *array,unsigned int *memo,int size)
- {
- // 默认最大子序列长度为0
- unsigned int maxlongsize=0;
- // 依次计算i到size-1
- for(int i=0;i<size;i++)
- {
- // 如果计算出来的子序列比maxlongsize大,就是计算出来的子序列的值,否则就是maxlongsize的值
- maxlongsize = maxnum(relongsequence(array,memo,i,size),maxlongsize);
- }
- // 返回最大子序列
- return maxlongsize;
- }
-
- int main(int argc,char *argv[])
- {
- // 定义一个序列
- unsigned int array[18]={3,7,4,8,5,9,3,4,2,1,0,4,5,6,2,3,4,6};
- // 用来保存每一个i位置的最长子序列的长度,默认为0
- unsigned int memo[18]={0};
-
- unsigned int longsizesequence=0;
- // 开始计算子序列
- longsizesequence = Maxlongsquence(array,memo,18);
- // 输出最大子序列的值
- cout<<longsizesequence<<endl;
-
- return 0;
- }
- //动态规划求解简化版本
-
- // 最长子序列的逆推法
- unsigned int Maxlongsquence2(unsigned int *array,unsigned int *meno,int arraysize)
- {
- // 从倒数第2个元素开始计算最长子序列,因为最后一个子序列的长度为1
- meno[arraysize-1]=1;
- int i=arraysize-2;
- // 从i的倒数第二个元素开始到第一个元素
- for(;i>=0;i--)
- {
- // j从i的第二个元素到最后一个元素
- for(int j=i+1;j<arraysize;j++)
- {
- // 如果i位置的值比j的值要小
- if(*(array+i)<*(array+j))
- {
- // 可以构成子序列
- meno[i]=maxnum(meno[i],meno[j]+1);
- }
- else
- {
- // 不可以构成子序列
- meno[i]=maxnum(meno[i],meno[j]);
- }
- }
-
- }
- // 返回最大子序列
- return meno[i+1];
- }
- int main(int argc,char *argv[])
- {
- // 定义一个序列
- unsigned int array[6]={1,9,2,4,2,9};
- // 用来保存每一个i位置的最长子序列的长度,默认为0
- unsigned int memo[6]={0};
-
- unsigned int longsizesequence=0;
- // // 开始计算子序列
- // longsizesequence = Maxlongsquence(array,memo,18);
- longsizesequence = Maxlongsquence2(array,memo,6);
- // 输出最大子序列的值
- cout<<longsizesequence<<endl;
-
- return 0;
- }
总结:动态规划算法的本质就是求解子问题,再将子问题的结果保存起来,当遇到重复的子问题时,就可以直接查表,取出已经得到的结果,不必继续求解同样的子问题.
动态规划使用空间来换取时间。