C++求解最长子序列(动态规划)

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;
}

总结:动态规划算法的本质就是求解子问题,再将子问题的结果保存起来,当遇到重复的子问题时,就可以直接查表,取出已经得到的结果,不必继续求解同样的子问题.

动态规划使用空间来换取时间。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值