求最长递减子列

求最大递减子列的三种方法

 假设有一段数列为 8 2 3 4 1 3 2,求该数列的最长递减子列

一.动态规划

f ( i ) 为 以 a [ i ] 为 结 尾 的 最 大 递 减 子 列 长 度 当 i > j 时 如 果 ( a [ I ] < = a [ j ] ) f [ I ] = m a x ( f [ j ] + 1 , f [ i ] ) f(i)为以a[i]为结尾的最大递减子列\\长度当i>j时\\ 如果(a[I]<=a[j])\\ f[I]=max(f[j]+1,f[i]) f(i)a[i]i>j(a[I]<=a[j])f[I]=max(f[j]+1,f[i])

#include <iostream>
using namespace std;
int main() {
    int n;
    int a[20];
    int f[20];
    int ans=-999999;
    scanf("%d",&n);
    for (int i=1; i<=n; i++) {
        scanf("%d",&a[i]);
        f[i]=1;
    }
    for (int i=1; i<=n; i++) {
        for (int j=1; j<i; j++) {
            if(a[j]>=a[i])                            f[i]=max(f[i],f[j]+1);
        }
    }
    for (int i=1; i<=n; i++) {
        ans=max(ans,f[i]);
    }
    printf("%d",ans);
    return 0;
}

二. 二分加贪心

以4 3 2 2 5 为例

43228
4
43
432
4322
8322

要用8替换4,这里是考虑一种可能性,因为可能在5
后还有数字,假设后面有7 6 6 5 4
那么这些会替换其他数字,获得更长

#include <iostream>
const int INF = -999999;
using namespace std;
int search(int *a,int r,int x)
{
    int l=1;
    int mid;
    while (l<=r) {
        mid=(l+r)/2;
        if(a[mid]<=x) r=mid-1;
        else l=mid+1;
    }
    return l;
}// 得到不小于x的a[i]的序数
int main() {
    int n;
    int a[20];
    int low[20];
    int ans=1;
    scanf("%d",&n);
    for (int i=1; i<=n; i++) {
        scanf("%d",&a[i]);
        low[i]=INF;
    }
    low[1]=a[1];
    for (int i=2; i<=n; i++) {
        if(a[i]<=low[ans]) low[++ans]=a[i];
        else low[search(low,ans,a[i])]=a[i];
    }
    printf("%d",ans);
    return 0;
}

三. 使用lower_bound( )函数

lower_bound( begin,end,num,cmp)查找第一个大于或等于num的地址
upper_bound( begin,end,num,cmp)查找第一个大于num的地址
他们被包含在

#include <algorithm>

可以用

#include <iostream>
#include <algorithm>
const int INF = -999999;
using namespace std;
int cmd(int x,int y)
{
    return x>y;
}
int main() {
    int n;
    int a[20];
    int low[20];
    int ans=1;
    scanf("%d",&n);
    for (int i=1; i<=n; i++) {
        scanf("%d",&a[i]);
        low[i]=INF;
    }
    low[1]=a[1];
    for (int i=2; i<=n; i++) {
        if(a[i]<=low[ans]) low[++ans]=a[i];
        else low[lower_bound(low,low+ans,a[i],cmd)-low]=a[i];
    }
    printf("%d",ans);
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值