UVALive 2678 利用序列的前缀来减少时间复杂度

本文介绍了一种算法,用于在给定的正整数序列中找到一个连续子序列,该子序列的和大于等于指定的目标值S,并且长度尽可能短。算法通过预处理前缀和数组并仅枚举序列的终点来实现O(n)的时间复杂度。

题意很简单,在一串正整数序列中找一个连续的子序列使该序列和大于等于一个已知量S,但要求序列长度最短,通常喜欢暴力枚举

这个题目跟大白书之前的一个题目很像,在数列A中 求 Ai-Aj最大 并且 i<J;这个题目巧妙一点,就直接只枚举j,然后在枚举j的过程中不断更新j前面的最大值即为Ai,即可只用O(n)的复杂度

同样,本题也是,先预处理下,把每个数的前缀和B求出来,这样求某一子序列 只要知道起终点,直接用B[J]-B[i]即可,只是枚举子序列的终点j,初始起点设置为i=0,如果满足B[j]-B[i]>=S,则不断增加i,否则,就增加j。这样只是枚举了一下终点,而找到起点几乎是常数时间。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int num[100010];
int B[100010];
int main()
{
    int n,s;
    while (scanf("%d%d",&n,&s)!=EOF)
    {
        for (int i=0;i<n;i++)
        {
            scanf("%d",&num[i]);
        }
        B[0]=0;
        for (int i=1;i<=n;i++)
        {
            B[i]=B[i-1]+num[i-1];
        }
        int ans=n+1;
        int i=0;
        for (int j=1;j<=n;j++)
        {
            int temp=B[j]-B[i];
            if (temp<s) continue;
            while (B[j]-B[i]>=s) i++;
            ans=min(ans,j-i+1);
        }
        if (ans==n+1) ans=0;
        printf("%d\n",ans);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/kkrisen/p/3553970.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值