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


    1.暴力求解法,时间复杂度为O(2^n)

    1. // 最长子序列问题求解
    2. // 比如序列:3,7,4,8,5,9
    3. // 最长子序列的长度为:4
    4. // 子序列为: 3,4,5,9.
    5. #include"iostream"
    6. using namespace std;
    7. // 求最大值函数
    8. unsigned int maxnum(unsigned int a,unsigned int b)
    9. {
    10. return a>b ? a:b;
    11. }
    12. // 暴力求解
    13. // 对当前位置i求解最大子序列
    14. unsigned int relongsequence(unsigned int *array,int i,int size)
    15. {
    16. // 默认长度为1
    17. unsigned int maxlong=1;
    18. // 对i位置的元素进行比较
    19. for(int j=i+1;j<size;j++)
    20. {
    21. // i位置小于j位置的值
    22. if(*(array+i)<*(array+j))
    23. {
    24. // 可以构成序列,继续对j位置进行求解出子序列的值,如果j位置的值比maxlong大,那就是计算出来的新maxlong值,否则就是maxlong.
    25. maxlong=maxnum(relongsequence(array,j,size)+1,maxlong);
    26. }
    27. }
    28. // 返回i位置最大序列
    29. return maxlong;
    30. }
    31. unsigned int Maxlongsquence(unsigned int *array,int size)
    32. {
    33. // 默认最大子序列长度为0
    34. unsigned int maxlongsize=0;
    35. // 依次计算i到size-1
    36. for(int i=0;i<size;i++)
    37. {
    38. // 如果计算出来的子序列比maxlongsize大,就是计算出来的子序列的值,否则就是maxlongsize的值
    39. maxlongsize = maxnum(relongsequence(array,i,size),maxlongsize);
    40. }
    41. // 返回最大子序列
    42. return maxlongsize;
    43. }
    44. int main(int argc,char *argv[])
    45. {
    46. // 定义一个序列
    47. unsigned int array[6]={3,7,4,8,5,9};
    48. unsigned int longsizesequence=0;
    49. // 开始计算子序列
    50. longsizesequence = Maxlongsquence(array,6);
    51. // 输出最大子序列的值
    52. cout<<longsizesequence<<endl;
    53. return 0;
    54. }

    2.动态规划算法求解,时间复杂度为O(n^2)

    1. // 最长子序列问题求解
    2. // 比如序列:3,7,4,8,5,9
    3. // 最长子序列的长度为:4
    4. // 子序列为: 3,4,5,9.
    5. #include"iostream"
    6. using namespace std;
    7. // 求最大值函数
    8. unsigned int maxnum(unsigned int a,unsigned int b)
    9. {
    10. return a>b ? a:b;
    11. }
    12. // 动态规划求解
    13. // 对当前位置i求解最大子序列
    14. unsigned int relongsequence(unsigned int *array,unsigned int *memo,int i,int size)
    15. {
    16. // 如果i位置的最长子序列已经计算出来了
    17. if(memo[i]!=0)
    18. {
    19. // 直接返回i位置的最长子序列
    20. return memo[i];
    21. }
    22. // 默认长度为1
    23. unsigned int maxlong=1;
    24. // 对i位置的元素进行比较
    25. for(int j=i+1;j<size;j++)
    26. {
    27. // i位置小于j位置的值
    28. if(*(array+i)<*(array+j))
    29. {
    30. // 可以构成序列,继续对j位置进行求解出子序列的值,如果j位置的值比maxlong大,那就是计算出来的新maxlong值,否则就是maxlong.
    31. maxlong=maxnum(relongsequence(array,memo,j,size)+1,maxlong);
    32. }
    33. }
    34. // 保存i位置的最长子序列
    35. memo[i]=maxlong;
    36. // 返回i位置最大序列
    37. return maxlong;
    38. }
    39. unsigned int Maxlongsquence(unsigned int *array,unsigned int *memo,int size)
    40. {
    41. // 默认最大子序列长度为0
    42. unsigned int maxlongsize=0;
    43. // 依次计算i到size-1
    44. for(int i=0;i<size;i++)
    45. {
    46. // 如果计算出来的子序列比maxlongsize大,就是计算出来的子序列的值,否则就是maxlongsize的值
    47. maxlongsize = maxnum(relongsequence(array,memo,i,size),maxlongsize);
    48. }
    49. // 返回最大子序列
    50. return maxlongsize;
    51. }
    52. int main(int argc,char *argv[])
    53. {
    54. // 定义一个序列
    55. unsigned int array[18]={3,7,4,8,5,9,3,4,2,1,0,4,5,6,2,3,4,6};
    56. // 用来保存每一个i位置的最长子序列的长度,默认为0
    57. unsigned int memo[18]={0};
    58. unsigned int longsizesequence=0;
    59. // 开始计算子序列
    60. longsizesequence = Maxlongsquence(array,memo,18);
    61. // 输出最大子序列的值
    62. cout<<longsizesequence<<endl;
    63. return 0;
    64. }
    1. //动态规划求解简化版本
    2. // 最长子序列的逆推法
    3. unsigned int Maxlongsquence2(unsigned int *array,unsigned int *meno,int arraysize)
    4. {
    5. // 从倒数第2个元素开始计算最长子序列,因为最后一个子序列的长度为1
    6. meno[arraysize-1]=1;
    7. int i=arraysize-2;
    8. // 从i的倒数第二个元素开始到第一个元素
    9. for(;i>=0;i--)
    10. {
    11. // j从i的第二个元素到最后一个元素
    12. for(int j=i+1;j<arraysize;j++)
    13. {
    14. // 如果i位置的值比j的值要小
    15. if(*(array+i)<*(array+j))
    16. {
    17. // 可以构成子序列
    18. meno[i]=maxnum(meno[i],meno[j]+1);
    19. }
    20. else
    21. {
    22. // 不可以构成子序列
    23. meno[i]=maxnum(meno[i],meno[j]);
    24. }
    25. }
    26. }
    27. // 返回最大子序列
    28. return meno[i+1];
    29. }
    30. int main(int argc,char *argv[])
    31. {
    32. // 定义一个序列
    33. unsigned int array[6]={1,9,2,4,2,9};
    34. // 用来保存每一个i位置的最长子序列的长度,默认为0
    35. unsigned int memo[6]={0};
    36. unsigned int longsizesequence=0;
    37. // // 开始计算子序列
    38. // longsizesequence = Maxlongsquence(array,memo,18);
    39. longsizesequence = Maxlongsquence2(array,memo,6);
    40. // 输出最大子序列的值
    41. cout<<longsizesequence<<endl;
    42. return 0;
    43. }

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

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

  • 相关阅读:
    修改node_modules中安装的依赖(如第三方ui组件样式)并在下次安装时保留
    Andriod Studio小游戏
    迷宫_随机实验_边做边学深度强化学习:PyTorch程序设计实践(1)
    机器学习——图片处理应用(人脸补全)
    圆角矩形不是圆:圆角的画法和二阶连续性
    R语言ggplot2可视化:使用ggpubr包的ggline函数可视化折线图(点线图、line plot)、同一水平的多个点用线连接起来
    Aspose.OCR 22.11.1 for .NET Crack
    Qt-QTransform-内存结构-仿射变换-工作原理-C++
    抖音推荐算法的底层逻辑,视频没有走到爆款中间经历了什么?
    Crypto(4)NewStarCTF 2023 week2 Crypto Rotate Xor
  • 原文地址:https://blog.csdn.net/weixin_53064820/article/details/126461937