有这么一类问题,需要在给的一组数据中找到不大于某一个上限的“最优连续子序列”

于是就有了这样一种方法,找这个子序列的过程很像毛毛虫爬行方式,我管它叫毛毛虫算法,比较流行的叫法是“尺取法”。

喏,就像图里的妹纸一样~

还是举个栗子:

Poj3061

给长度为n的数组和一个整数m,求总和不小于m的连续子序列的最小长度

输入

n = 10,m = 15

5 1 3 5 10 7 4 9 2 8

输出

2

那么我们先用sum存当前这个子序列的和,从左边第一个数来存,直到这个子序列的和大于等于m为止,再记录下当前长度。

其实相当于当不满足条件就入队,然后得到队列长度,再将队首元素出队,再进行下一次的入队,直到满足条件再次出队,并且将这一次的长度与历史最短长度进行取舍,最后扫到最后的元素却无法再满足入队条件的时候就结束,此时用O(n)的时间就可以得到答案。

如下,我把样例用毛毛虫爬一遍,下划线的是当前“毛毛虫着地”也就是刚好满足题意的子序列的地方:

5 1 3 5 10 7 4 9 2 8

1 3 5 10 7 4 9 2 8

5 13 5 10 7 4 9 2 8

5 1 3 5 10 7 4 9 2 8

5 1 3 5 10 7 4 9 2 8

5 1 3 5 10 7 4 9 2 8

5 1 3 5 107 4 9 2 8

5 1 3 5 10 7 4 9 2 8

5 1 3 5 10 7 4 9 2 8

祖传代码。。。

C++

/*************************************************************************> File Name: main.cpp> Author: haoran> Created Time: 2015年01月19日 星期一 21时04分36秒************************************************************************/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <fstream>
#include <algorithm>
using namespace std;
int a[200000];
int main()
{
//  freopen("in.txt","r",stdin);ios::sync_with_stdio(false);cin.tie(false);int n,max,sum,T;while(cin>>T){while(T--){cin>>n>>max;for(int i = 0 ; i < n ; i++)cin>>a[i];int i = 0,j = 0,sum = 0,ans = n+1;while(1){while(j < n && sum <= max)sum += a[j++];if(sum < max) break;ans = min(j-i,ans);sum -= a[i++];}if(ans > n)ans = 0;printf("%d\n",ans);}}return 0;
}

java大法的

import java.util.Scanner;public class Main {/*** @param args*/public static void main(String[] args) {// TODO Auto-generated method stubScanner cin = new Scanner(System.in);int a[] = new int[100010];int T = cin.nextInt();for(int ii = 0 ; ii < T ; ii++){int n = cin.nextInt();int m = cin.nextInt();for(int i = 0 ; i < n ; i++)a[i] = cin.nextInt();int l = 0,r = 0,ans = m+1,sum = 0;while(true){while(r < n && sum < m)sum += a[r++];if(sum < m)break;ans = min(ans,r-l);sum -= a[l++];}if(ans > n)ans = 0;System.out.println(ans);}}private static int min(int ans, int sum) {// TODO Auto-generated method stubreturn ans < sum ? ans : sum;}
}

买一送一,再给大家一颗栗子;

Poj3320

这道题费点脑子,大意:

一个考前一天看一整本书发呆的学渣,找学霸划知识点,学霸告诉他每一页的知识点(每一页只有一个知识点而且页与页之间可以重复知识点!),每一个知识点都用一个数字表示,给你这本书一共有n页厚,学渣很懒,只想读连续若干页的书,还不想看太多页,所以要你帮他找覆盖所有出现过的知识点的连续页的页数最薄有几页。

输入

n = 5

1 8 8 8 1

输出

2

很显然一共有5页书,却只有2个知识点,想读就读前两页,所以就输出2页。先想想需要解决什么问题:

1.要解决出现一共多少个知识点

2.根据当前子序列包含的知识点数来入队、出队

其实就这样。

第一个问题其实可以用set来解决,知识点数量就是set的size大小。

下一个问题其实可以用map来存,存每一页出现的知识点在这个子序列中出现的次数,如果是0的话就把这个知识点放进来并++,直到所有知识点覆盖为止。

在所有知识点覆盖的基础上出队,直到某一个知识点在子序列的出现次数为0的时候,再从后面入队,并在这些操作中记录下最少页数就可以了,剩下的和第一颗栗子一个味道。

祖传C++代码如下~

#include <iostream>
#include <map>
#include <set>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cstring>
using namespace std;
int n,m,a[1000010];
void solve()
{set<int> all ;map<int,int>cnt;for(int i = 0 ; i < n ; i++){scanf("%d",&a[i]);all.insert(a[i]);}m = all.size();int l = 0 , r = 0 , ans = n+1,sum = 0;while(1){while(r < n && sum < m)if(cnt[ a[r++] ]++ == 0)sum++;if(sum < m)break;ans = min(ans,r-l);if(--cnt[ a[l++]  ] == 0)sum--;}printf("%d\n",ans);
}
int main()
{#ifdef H_Rfreopen("in.txt","r",stdin);#endif // H_Rwhile(scanf("%d",&n)!=EOF){solve();}return 0;
}

毛毛虫算法——尺取法相关推荐

  1. 数据结构9-双指针(尺取法)(double pointer)

    双指针有好几种,但是最常用的是尺取法,所以有的时候就说尺取法 双指针,指的是在遍历对象的过程中,不是普通的使用单个指针进行访问,而是使用两个相同方向(快慢指针)或者相反方向(对撞指针)的指针进行扫描, ...

  2. 算法篇之-----滑动窗口(尺取法)

    滑动窗口(尺取法 1. 介绍 2. 滑动窗口法的大体框架 4.最小覆盖子串 5.窗口数量 6.最小值 1. 介绍 滑动窗口法,也叫尺取法(可能也不一定相等,大概就是这样 =.=),可以用来解决一些查找 ...

  3. 尺取法 --算法竞赛专题解析(2)

    本系列文章将于2021年整理出版,书名<算法竞赛专题解析>. 前驱教材:<算法竞赛入门到进阶> 清华大学出版社 2019.8 网购:京东 当当      作者签名书 如有建议, ...

  4. 尺取--(毛毛虫算法)

    尺取算法也叫毛毛虫算法,因为计算过程有点类似毛毛虫一点点的往前挪,在挪动的过程中可以得到一些需要的解.(自动脑补) 通过两个变量来保存所选取区间的左右端点,然后不断的推进区间,寻找所需要的答案(尺取的 ...

  5. Codeforces 1548B Integers Have Friends 尺取法 Hdu 7073 Integers Have Friends 2.0 力能扛鼎随机算法

    文章目录 题意 题解 CF1548B 题解 Hdu 7073 CF1548B HDU7073 题意 定义数的好友组为一个集合SSS,取正整数m>1,∀x∈s,xmodmm>1,\foral ...

  6. CF660C Hard Process(尺取法)

    整理的算法模板合集: ACM模板 尺取法 题目中要我们求最多改变k次后连续的1的最长长度.那么转换一下,不就是求至多包含k个0的子串的最长长度吗? 直接套用尺取法的思想,维护两端点,一旦0的个数超过k ...

  7. 【常用技巧精选】尺取法

    整理的算法模板合集: ACM模板 目录 1.反向扫描 1 找指定和的整数对 A.UVA1121 Subsequence B.POJ 3320 Jessica's Reading Problem C.l ...

  8. poj2566Bound Found尺取法进阶(java)

    题目链接: 这个尺取法的思想挺好的,如果第一次做尺取法题,不妨看下尺取法入门题. 题目大意: 多组测试数据(0,0)截止. 每组数据输入 n,k(n数字个数,k询问次数) 下一行n个数表示序列. 接下 ...

  9. poj3320Jessica's Reading Problem—尺取法(java)

    题目链接 大意:给序列数字,找出最小子序列,包含所有的元素类型.例如 5 1 8 8 8 1 输出2,因为1 8就包含了所有元素 思路:尺取法 这个和裸的尺取优点不同的是,他需要一个map来维护判断而 ...

最新文章

  1. c266 设置邮箱_工作邮件如何写?—有效沟通才是你的核心竞争力
  2. oracle入门知识实施,新手必须了解的oracle入门知识
  3. php分布式cache,thinkPHP实现MemCache分布式缓存功能
  4. aws终止实例后还收费吗_因 AWS 数据中心断电,1TB 数据丢失了
  5. php input 数组的值,如何获取2值表单输入数组到PHP数组中(How to get 2 value form input array into PHP array)...
  6. 字典:散列表、散列字典、关键字列表、集合与结构体
  7. map型字段 mongodb_MongoDB极简教程
  8. java比较时间的先后utc时间,日期、时间与UTC
  9. MySQL 创建用户
  10. MySQL工作笔记-编写存储过程批量添加数据
  11. BootstrapTable分页(一)
  12. WEB前端响应式布局之BootStarp使用
  13. C#绘制立体三维饼状图(超酷)
  14. react使用antd实现日期与时间的不可选定
  15. 【Luogu2085】最小函数值(优先队列)
  16. L2-007 家庭房产(并查集)
  17. linux 查看进程关系树
  18. moss 自定义文档库文档图标
  19. 图像特征提取之LBP算法
  20. java drawline变黑,为什么java.awt.Graphics.drawLine特别慢?

热门文章

  1. 工程伦理--7.3 公平原则
  2. IIS7 404 模块 IIS Web Core 通知 MapRequestHandler 处理程序 StaticFile 错误代码 0x80070002
  3. matlab生成行向量组,什么叫行向量组与列向量组? 什么是矩阵的维度?
  4. 售前工程师工作内幕揭秘:基础认知
  5. 计算机应用基础山东省,《计算机应用基础/山东省高校教改项目立项教材》低价购书_计算机与互联网_孔网...
  6. Charles抓包手机连不上网,遇到的天坑
  7. AI 移动之 Steering操控力算法
  8. 斐波那契数列/黄金分割数列/“兔子数列”
  9. SPI硬件设计、协议、速率全解析
  10. C语言清除缓冲区的函数