尺取法

尺取法:

顾名思义,像尺子一样取一段,借用挑战书上面的话说,尺取法通常是对数组保存一对下标,即所选取的区间的左右端点,然后根据实际情况不断地推进区间左右端点以得出答案。尺取法比直接暴力枚举区间效率高很多,尤其是数据量大的时候,所以说尺取法是一种高效的枚举区间的方法,是一种技巧,一般用于求取有一定限制的区间个数或最短的区间等等。当然任何技巧都存在其不足的地方,有些情况下尺取法不可行,无法得出正确答案,所以要先判断是否可以使用尺取法再进行计算。

 

使用尺取法时应清楚以下四点:

1、  什么情况下能使用尺取法?  2、何时推进区间的端点? 3、如何推进区间的端点? 4、何时结束区间的枚举?

 

    尺取法通常适用于选取区间有一定规律,或者说所选取的区间有一定的变化趋势的情况,通俗地说,在对所选取区间进行判断之后,我们可以明确如何进一步有方向地推进区间端点以求解满足条件的区间,如果已经判断了目前所选取的区间,但却无法确定所要求解的区间如何进一步得到根据其端点得到,那么尺取法便是不可行的。首先,明确题目所需要求解的量之后,区间左右端点一般从最整个数组的起点开始,之后判断区间是否符合条件在根据实际情况变化区间的端点求解答案。

 

借助问题来进一步去理解尺取法

 

问题【1】

给你一个序列(大小为n),让你去找到一个区间[i,j] , 区间内所有数的和 sum >= 15 求出满足这样要求的最小的区间长度

 

#include <cstdio>
#include <string>
#include <iostream>
#include <algorithm>
#include <cstdbool>
#include <string.h>
#include <math.h>

using namespace std;

//5 1 3 5 10 7 4 9 2 8

int main()
{
    int a[10] = {5,1,3,5,10,7,4,9,2,8};
    int i = 0,j = 0,ans = 100;
    int sum = a[0];
    while (i <= j && j < 10)
    {
        if (sum >= 15)
        {
            //   ans = min(ans,j-i+1);
            if (sum == 15)
            {
              //  printf("i = %d j = %d\n",i+1,j+1);
                ans = min(j-i+1,ans);
                sum -= a[i];
                i++;
            }
            else
            {
                ans = min(ans,j-i+1);
                sum -= a[i];
                i++;
            }
        }
        else
        {
            j++;
            sum += a[j];
        }
    }
   printf("%d\n",ans);
    return 0;
}
View Code

 

问题【2】

给定一个由若干 0 和 1 组成的数组 A,我们最多可以将 K 个值从 0 变成 1 。

返回仅包含 1 的最长(连续)子数组的长度。

 

示例 1:

输入:A = [1,1,1,0,0,0,1,1,1,1,0], K = 2
输出:6
解释:
[1,1,1,0,0,1,1,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 6。
示例 2:

输入:A = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1], K = 3
输出:10
解释:
[0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 10。
 

提示:

1 <= A.length <= 20000
0 <= K <= A.length
A[i] 为 0 或 1 

 

#include <cstdio>
#include <string>
#include <iostream>
#include <algorithm>
#include <cstdbool>
#include <string.h>
#include <math.h>

using namespace std;

//5 1 3 5 10 7 4 9 2 8
char a[20005];

int main()
{
    int a[11]={1,1,1,0,0,0,1,1,1,1,0};  //这里数组是定死定,你也可以自己输入
    int left = 0;
    int res = 0;
    int k;
    cin >> k;
    for (int right = 0;right < 11;right++)
    {
        if (a[right] == 0)
            k--;
        if (k < 0)
        {
            if (a[left] == 0)
                k++;
            left++;
        }
        res = max(res,right-left+1);
    }
    printf("%d\n",res);
    return 0;
}
View Code

 

全部评论

相关推荐

02-01 12:05
复旦大学 Java
腾讯的提前批大概率应该是没有笔试的,但是这个时候有相当部分的同学简历估计都没有准备好,没准备好的同学也不用急,大部分都是3月之后开,这个时候开的绝大多数都是神仙打架,问的东西也比较难,打算投递的同学也多看下计算机网络和操作系统,腾讯对这部分的知识问的比较多。另外多刷下牛客的热门题库,刷题注意刷ACM模式,和牛客的周赛题,腾讯有的部门会从这里面出原题。我是@程序员花海关注我,带你了解更多校招资讯!
程序员花海:还没有来得及准备的同学可以看下学习路线:https://www.nowcoder.com/discuss/824693499982315520?sourceSSR=users算法题:https://www.nowcoder.com/feed/main/detail/20e7a999fa04485b88340a274411ca0d?sourceSSR=users八股文:https://www.nowcoder.com/discuss/833102362771251200?sourceSSR=users简历书写方式:https://www.nowcoder.com/discuss/839907820706205696?sourceSSR=users都是以前在牛客发的文章~
软开人,秋招你打算投哪些...
点赞 评论 收藏
分享
2025-12-18 11:59
广州南方学院 C++
牛客78682892...:直接点还好,总比要了简历也不回的强
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务