数据结构和算法笔记1:滑动窗口

news/2024/5/20 10:10:20 标签: 算法, 数据结构, 滑动窗口

在一些数组或者字符串我们需要遍历子序列,可能要用到两个指针(我们称为起始指针和终止指针)进行双层遍历,内层终止指针满足条件时跳出内层循环,然后起始指针前进,回溯终止指针到起始指针,以此继续进行遍历,然而这样效率比较低,我们可能进行了很多不必要的比较。有没有可能只进行一次遍历呢?滑动窗口提供了一个很好的思路。

滑动窗口算法中我们要解决以下问题:

  • 窗口内是什么?

窗口就是满足条件的子序列。

  • 如何移动窗口的起始位置?

当前窗口的值满足条件了,窗口的起始指针就要向前移动了(也就是该缩小窗口)。

  • 如何移动窗口的结束位置?

窗口的结束位置就是遍历数组的终止指针,也就是一次遍历(for循环)的索引。把整个数组遍历完,终止指针到了最后一个索引,移动窗口就结束了。


代码模板:

int i = 0, j = 0;//i是终止指针,j是起始指针
for (; i < s..size(); i++)//s是序列,i是一遍遍历的终止指针
{
	//对s[i]的操作
  
  // 窗口满足条件就更新数据,起始指针要移动
  while(窗口满足条件){
  	//记录或更新数据
  	...
  	
  	//起始指针移动一位
  	j++;

	//记录或更新数据
  	...
  }
  //返回结果

练习题:牛客网-牛牛的数组匹配

牛牛刚学会数组不久,他拿到两个数组 a 和 b,询问 b 的哪一段连续子数组之和与数组 a 之和最接近。
如果有多个子数组之和同样接近,输出起始点最靠左的数组。

输入描述:

第一行输入两个正整数 n 和 m ,表示数组 a 和 b 的长度。 第二第三行输入 n 个和 m 个正整数,表示数组中 a 和 b 的值。

输出描述:

输出子数组之和最接近 a 的子数组

示例1

输入:
2 6
30 39
15 29 42 1 44 1

输出:
29 42

示例2

输入:
6 1
50 47 24 19 46 47
2

输出:
2

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

int main() {
    int n, m;
    cin >> n >> m;
    int a[n], b[m];
    int sum_a = 0; 
    int sum_b = 0;
    for (int i = 0; i < n; ++i)
    {
        cin >> a[i];
        sum_a += a[i];
    }
    for (int i = 0; i < m; ++i)
    {
        cin >> b[i];
    }
    int j = 0;
    int left = 0, right = 0;
    int res = abs(b[0] - sum_a);//初始化b子序列和sum_b和sum_a的差
    for (int i = 0; i < m; i++)
    {
        sum_b += b[i];

        while (sum_b >= sum_a)//找到sum_b中超过sum_a的分界线,sum_b-b[i]<sum_a,sum_b>=sum_a
        {
            
            if (sum_b - b[i] > 0) //sum_b由两个及以上的数相加而成(sum_b >= sum_a)
            {
                if (abs(sum_b - b[i] - sum_a) < abs(sum_b - sum_a))//sum_b-b[i]比sum_b更接近sum_a
                {
                    if (abs(sum_b - b[i] - sum_a) < res)//找到更接近sum_a的和:sum_b - b[i],更新起始指针和终止指针
                    {
                        right = i - 1;
                        left = j;
                        res = abs(sum_b - b[i] - sum_a);
                    }
                    sum_b -= b[j++];
                }
                else if (abs(sum_b - b[i] - sum_a) > abs(sum_b - sum_a))//sum_b比sum_b-b[i]更接近sum_a
                {
                    if (abs(sum_b - sum_a) < res)//找到更接近sum_a的和:sum_b,更新起始指针和终止指针
                    {
                        right = i;
                        left = j;
                        res = abs(sum_b - sum_a);
                    }
                    sum_b -= b[j++];
                }
            }
            else //sum_b由一个数相加而成(sum_b >= sum_a)
            {
                right = i;
                left = j;
                res = abs(sum_b - sum_a);
                sum_b -= b[j++];
            }
        }
        if ((i == m - 1) && (j == 0))//排除b数组所有数之和都小于a数组之和情况
        {
        	right = i;
            left = j;
        }     
    }
    
    for (int i = left; i <= right; i++)
        cout << b[i] << " ";
}

力扣的209.长度最小的子数组也是滑动窗口的典型应用,也可以想想。解法在代码随想录有详解,就不赘述了: 代码随想录-209.长度最小的子数组


http://www.niftyadmin.cn/n/5072889.html

相关文章

数据科学最佳实践:Kedro 的工程化解决方案 | 开源日报 No.47

leonardomso/33-js-concepts Stars: 58.4k License: MIT 这个项目是一个帮助开发者掌握 JavaScript 概念的资源库。该项目基于 Stephen Curtis 撰写的一篇文章&#xff0c;包含了对 33 个重要 JavaScript 概念全面深入地讲解&#xff0c;并被 GitHub 评为 2018 年最佳开源项目…

理解ES的refresh、flush、merge

一、refresh 对于任何数据库的写入来讲fsync刷盘虽然保证的数据的安全但是如果每次操作都必须fsync一次&#xff0c;那fsync操作将是一个巨大的操作代价&#xff0c;在衡量对数据安全与操作代价下&#xff0c;ES引入了一个较轻量的操作refresh操作来避免频繁的fsync操作。 1.1…

linux 分区 添加 挂载centos挂载 Microsoft basic

​ 一 背景 es 忽然写不进去了 报错 TOO_MANY_REQUESTS/12/disk usage exceeded flood-stage watermark查看发现 磁盘已经满了 2T 的磁盘已经使用完了 ​ fdisk -l 查看原来磁盘有64000G 有64T 装机的人只分区了2T,白白浪费58T. 二 添加分区 利用剩余的空间 1添加分区 添…

springboot框架拦截器中HttpServletRequest 请求如何区分是图片上传流还是普通的字符流?

在Spring Boot框架中的拦截器&#xff08;Interceptor&#xff09;中&#xff0c;可以通过检查Content-Type请求头来区分图片上传流和普通的字符流。 当客户端发送POST请求并携带文件时&#xff0c;Content-Type请求头通常会包含multipart/form-data或者类似的值。这表明该请求…

科技云报道:押注向量数据库,为时过早?

科技云报道原创。 在大模型的高调火热之下&#xff0c;向量数据库也获得了前所未有的关注。 近两个月内&#xff0c;向量数据库迎来融资潮&#xff0c;Qdrant、Chroma、Weaviate先后获得融资&#xff0c;Pinecone宣布1亿美元B轮融资&#xff0c;估值达到7.5亿美元。 东北证券…

助力农作物病虫害检测识别,基于yolov3—yolov8开发构建马铃薯作物甲虫检测识别系统

AI加持的智慧农业也是一个比较有前景的赛道&#xff0c;近些年来已经有很多不错的方向做出来成绩&#xff0c;基于AI的激光除草、灭虫等也是其中的一个热门&#xff0c;杂草相关的检测识别在我们之前的项目实例中已经有相关的实践了&#xff0c;这里本文的主要目的就是以农作物…

vue3 vscode no tsconfig与找不到名称“ref”。ts(2304)

如题&#xff0c;这两个问题都与tsconfig的配置有关&#xff0c;先看下问题表现&#xff1a; 解决方法&#xff0c;应当正确配置如下&#xff0c;之后保存或重启vscode&#xff1a;