尺子算法

先来介绍一下尺取法。尺取法,顾名思义,像尺子一样,一块一块的截取。是不是解释的有点让人纳闷~。。没关系,下面我们通过这个题目来体会尺取法的魅力。

题目翻译:

  给定长度为n的数列整数a0,a1,a2,a3 ….. an-1以及整数S。求出综合不小于S的连续子序列的长度的最小值。如果解不存在,则输出0。

  限制条件:

    10

    0

    S<10^8

这里我们拿第一组测试数据举例子,即 n=10, S = 15, a = {5,1,3,5,10,7,4,9,2,8}

这里写图片描述

   这幅图便是尺取法怎么“取”的过程了。

  整个过程分为4步:

    1.初始化左右端点

    2.不断扩大右端点,直到满足条件

    3.如果第二步中无法满足条件,则终止,否则更新结果

    4.将左端点扩大1,然后回到第二步

用尺取法来优化,使复杂度降为了O(n)。

最后,再给一个尺取法的定义以便更好理解:返回的推进区间开头和结尾,求满足条件的最小区间的方法称为尺取法。

以上为网上关于尺取法的原理介绍,还是比较好理解的,邢如蚯蚓的爬动。

直接上代码:

#include<iostream>
#include<algorithm>
using namespace std;

int const MAXN = 10;
int const S = 15;
int sequence[MAXN] = { 16,4,9,2,8,5,1,3,4,12,};

int slove(int sequence[])
{
    int s = 0, t = MAXN, sum = 0, i = 0;
    int res = MAXN + 1;
    while (1)
    {
        while (sum < S && i < MAXN)
        {
            sum += sequence[i++];
        }
        if (sum < S)
        {//如果全部加起来都
            return res;
        }

        res = min(res, (i - s));//获取尺子长度

        if (res > MAXN)
        {
            printf("not find \n");
            return res;
        }
        sum -= sequence[s];//尺子头往后挪一个
        s++;//尺子的起点
    }
}

int main(int argc)
{
    int res = slove(sequence);
    printf("res is %d\n", res);
    return 0;
}

一道题
描述
如果一个字符串恰好包含2个’h’、1个’i’和1个’o’,我们就称这个字符串是hiho字符串。

例如”oihateher”、”hugeinputhugeoutput”都是hiho字符串。

现在给定一个只包含小写字母的字符串S,小Hi想知道S的所有子串中,最短的hiho字符串是哪个。

输入
字符串S

对于80%的数据,S的长度不超过1000

对于100%的数据,S的长度不超过100000

输出
找到S的所有子串中,最短的hiho字符串是哪个,输出该子串的长度。如果S的子串中没有hiho字符串,输出-1。

样例输入
happyhahaiohell
样例输出
5

#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
using namespace std;

const int INF = 0x3f3f3f3f;

int ch[100005], ci[100005], co[100005];

bool check(int pos, int a, int b, int c)
{
    return ch[pos] <= a - 2 && ci[pos] <= b - 1 && co[pos] <= c - 1;
}

int main()
{
    string s;
    cin >> s;
    int n = s.length();
    ch[0] += (s[0] == 'h');
    ci[0] += (s[0] == 'i');
    co[0] += (s[0] == 'o');
    int last = 0, min_len = INF;
    for (int i = 1; i < n; i++)
    {
        ch[i] = ch[i - 1] + (s[i] == 'h');
        ci[i] = ci[i - 1] + (s[i] == 'i');
        co[i] = co[i - 1] + (s[i] == 'o');
        if (ch[i] >= 2 && ci[i] >= 1 && co[i] >= 1)
        {
            while (last < i && check(last, ch[i], ci[i], co[i]))
            {
                last++;//找到最短的那个字符间距
            }
            if (ch[i] - ch[last - 1] == 2 && 
                ci[i] - ci[last - 1] == 1 && 
                co[i] - co[last - 1] == 1) 
                min_len = min(min_len, i - last + 1);
        }
    }
    if (min_len != INF)
        cout << min_len << endl;
    else
        cout << -1 << endl;
    return 0;
}

恰好2个’h’,1个’i’,1个’o’。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值