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;
}
总结:动态规划算法的本质就是求解子问题,再将子问题的结果保存起来,当遇到重复的子问题时,就可以直接查表,取出已经得到的结果,不必继续求解同样的子问题.
动态规划使用空间来换取时间。