• 最长不下降子序列


    上升子序列:元素各不相同

    不下降子序列:元素可以相同

    即   将上升子序列改一个if条件里面的即可

    1. //最长不下降子序列
    2. #include
    3. #include
    4. #include
    5. #include
    6. using namespace std;
    7. const int N = 100010;
    8. int a[N],f[N];
    9. int n;
    10. int main()
    11. {
    12. int ans = 1;
    13. cin>>n;
    14. for(int i = 1;i <= n;i++)
    15. {
    16. f[i] = 1;
    17. }
    18. for(int i = 2;i <= n;i++)
    19. {
    20. for(int j = 1;j <= i;j++)
    21. if(a[i] >= a[j])f[i] = max(f[i],f[j]+1);
    22. ans = max(ans,f[i]);
    23. }
    24. cout<
    25. return 0;
    26. }

    若用二分查找就要改两处

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. const int N = 2020;
    6. int a[N],f[N];//f[]记录上升子序列
    7. int len;//上升子序列的长度
    8. int find(int x)//二分查找第一个大于x的位置
    9. {
    10. int l = 1,r = len,mid;
    11. while(l <= r)
    12. {
    13. mid = (l+r)>>1;
    14. if(x >= f[mid]) l = mid+1;
    15. else r = mid-1;
    16. }
    17. return l;
    18. }
    19. //也不是不可以用lower_bound( )
    20. int main()
    21. {
    22. cin>>n;
    23. len = 1;
    24. for(int i = 1;i <= n;i++)cin>>a[i];
    25. f[1] = a[1];//把第一个元素添加进f[ ]中
    26. //考虑新加进来的a[i]
    27. for(int i = 2;i <= n;i++)
    28. {
    29. //大于则添加
    30. if(a[i] >= f[len])f[++len] = a[i];
    31. else//小于等于则替换
    32. {
    33. int j = find(a[i]);
    34. f[j] = a[i];
    35. }
    36. }
    37. cout<
    38. return 0;
    39. }

    若我们要输出不下降子序列里的最长上升子序列怎么办呢?

    那我们这时候就需要用一个pre[ ]数组来记录原数组a[ ] 的下标(ps:这里是前一个元素下标)

    二分查找的优点:求解长度快

    缺点:不能输出子序列!!!

    所以这里我们需要用第一种方法即可

    1. #include
    2. #include
    3. #include
    4. using namespace std;
    5. const int N = 1020;
    6. int a[N],f[N],pre[N];
    7. int longlen;
    8. int n;
    9. void print(int i)
    10. {
    11. if(pre[i]) print(pre[i]);
    12. printf("%d ",a[i]);
    13. }
    14. int main()
    15. {
    16. int ans = 1;
    17. scanf("%d",&n);
    18. for(int i = 1;i <= n;i++)f[i] = 1;
    19. for(int i = 2;i <= n;i++)
    20. {
    21. for(int j = 1;j < i;j++)
    22. if(a[i] > a[j] && f[i] < f[j] + 1)
    23. {
    24. f[i] = f[j] + 1;
    25. pre[i] = j;//记录前驱
    26. }
    27. if(f[i] > ans)
    28. {
    29. ans = f[i];
    30. longlen = i;
    31. }
    32. }
    33. printf("%d\n",ans);
    34. print(longlen);
    35. return 0;
    36. }

  • 相关阅读:
    Node.js学习(二)
    java八股文面试[数据库]——慢查询优化
    剑指offer——JZ27 二叉树的镜像 解题思路与具体代码【C++】
    国内项目管理中级证书CSPM-3正在报名!
    Linux 线程控制 —— 线程取消 pthread_cancel
    JavaEE开发之SpringMVC框架整合1
    Django笔记三十七之多数据库操作(补充版)
    尚硅谷尚品项目汇笔记(三)
    内存取证工具Volatility学习
    Linux调试器--gdb使用
  • 原文地址:https://blog.csdn.net/Demilly123/article/details/127796574