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

这篇具有很好参考价值的文章主要介绍了数据结构和算法笔记1:滑动窗口。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 算法原理

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

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

  • 窗口内是什么?

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

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

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

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

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


代码模板:

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

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

2. 典型习题

牛客网-牛牛的数组匹配

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

#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.长度最小的子数组

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

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
    
        int i = 0;
        int j;//j一定在i的前面
        int sum = 0;
        int res = INT32_MAX;
        for (j = 0; j < nums.size(); j++)
        {
            sum = sum + nums[j];
            while (sum >= target)
            {
                if (res > (j - i + 1))
                {
                    res = (j - i + 1);
                }
                sum = sum - nums[i];
                ++i;
            }
        }
        if (res == INT32_MAX)
            return 0;
        return res;
    }
};

904.水果成篮

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

class Solution {
public:
    int totalFruit(vector<int>& fruits) {
        int len = fruits.size();
        vector<int> basket(len + 5, 0);
        int total = 0;

        int maxSum = 0;
        
        for (int i = 0, j = 0; i < len; ++i)
        {
            basket[fruits[i]]++;
            if (basket[fruits[i]] == 1)
            {
                total++;
            }
            while (total > 2)
            {
                basket[fruits[j]]--;
                if (basket[fruits[j]] == 0)
                    total--;
                j++;
            }
            maxSum = max(maxSum, i - j + 1);
        }
        return maxSum;


    }
};

76.最小覆盖子串

数据结构和算法笔记1:滑动窗口,算法和数据结构,算法,数据结构,滑动窗口文章来源地址https://www.toymoban.com/news/detail-727920.html

class Solution {
public:
    string minWindow(string s, string t) {
        unordered_map<char, int> tMp;
        for (int i = 0; i < t.size(); ++i)
            tMp[t[i]]++;
        int len = s.size();
        int minStrSize = INT_MAX;
        int ans_left = 0; // 保存最小窗口的左边界
        int ans_right = -1; // 保存最小窗口的右边界
        string res;
        for (int i = 0, j = 0; i < s.size(); ++i)
        {
            if (tMp.find(s[i]) != tMp.end())
            {
                tMp[s[i]]--;
                
            }
            while (match(tMp))
            {
                if (i - j + 1 < minStrSize)
                {
                    ans_left = j;
                    ans_right = i;
                    minStrSize = i - j + 1;
                    
                }
                if (tMp.find(s[j]) != tMp.end())
                {
                    tMp[s[j]]++;
                }
                ++j;
            } 
        }
        return s.substr(ans_left, ans_right - ans_left + 1);
    }
    bool match(unordered_map<char, int>& map)
    {
        for (auto &p: map)
        {
            if (p.second > 0)
                return false;
        }
        return true;
    }
};

到了这里,关于数据结构和算法笔记1:滑动窗口的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构之栈、队列——算法与数据结构入门笔记(四)

    本文是算法与数据结构的学习笔记第四篇,将持续更新,欢迎小伙伴们阅读学习 。有不懂的或错误的地方,欢迎交流 栈是一种线性数据结构,其 只允许在固定的一端进行插入和删除 元素操作。进行数据插入和删除操作的一端称为栈顶 (Top), 另一端称为栈底 (Bottom)。栈中的

    2024年02月08日
    浏览(39)
  • 数据结构和算法笔记4:排序算法-归并排序

    归并排序算法完全遵循分治模式。直观上其操作如下: 分解:分解待排序的n个元素的序列成各具n/2个元素的两个子序列。 解决:使用归并排序递归地排序两个子序列。 合并:合并两个已排序的子序列以产生已排序的答案。 我们直接来看例子理解算法的过程,下面是要排序

    2024年01月21日
    浏览(64)
  • 数据结构之树与二叉树——算法与数据结构入门笔记(五)

    本文是算法与数据结构的学习笔记第五篇,将持续更新,欢迎小伙伴们阅读学习。有不懂的或错误的地方,欢迎交流 前面章节介绍的都是线性存储的数据结构,包括数组、链表、栈、队列。本节带大家学习一种非线性存储的数据结构,即树(tree)。 不管是在面试时,还是日

    2024年02月08日
    浏览(50)
  • 【王道考研】王道数据结构与算法详细笔记(全)

    目录 第一章 数据结构绪论  1.1 数据结构的基本概念 1.2 数据结构的三要素 1.2.1. 数据的逻辑结构 1.2.2. 数据的存储结构(物理结构) 1.2.3. 数据的运算 1.2.4. 数据类型和抽线数据类型 1.3 算法的基本概念 1.4 算法的时间复杂度 1.5 算法的空间复杂度 第二章 线性表 2.1 线性表的定

    2024年02月08日
    浏览(53)
  • 【学习笔记】数据结构算法文档(类C语言)

    1.1.1 线性表的顺序存储表示 1.1.2 顺序表中基本操作的实现 1.1.2.1 初始化 1.1.2.2 取值 1.1.2.3 查找 1.1.2.4 插入 1.1.2.5 删除 1.1.2.6 计数 1.2.1 单链表的定义和表示 ★ 关于结点 1.2.2 单链表基本操作的实现 1.2.2.1 初始化 1.2.2.2 取值 1.2.2.3 查找 1.2.2.4 插入 1.2.2.5 删除 1.2.2.6 前插法创建单

    2024年02月07日
    浏览(44)
  • 读书笔记-《数据结构与算法》-摘要8[桶排序]

    桶排序和归并排序有那么点点类似,也使用了归并的思想。大致步骤如下: 设置一个定量的数组当作空桶。 Divide - 从待排序数组中取出元素,将元素按照一定的规则塞进对应的桶子去。 对每个非空桶进行排序,通常可在塞元素入桶时进行插入排序。 Conquer - 从非空桶把元素

    2024年01月18日
    浏览(43)
  • 读书笔记-《数据结构与算法》-摘要4[插入排序]

    核心:通过构建有序序列,对于未排序序列,在已排序序列中从后向前扫描(对于单向链表则只能从前往后遍历),找到相应位置并插入。实现上通常使用in-place排序(需用到O(1)的额外空间) 从第一个元素开始,该元素可认为已排序 取下一个元素,对已排序数组从后往前扫描 若从

    2024年02月04日
    浏览(37)
  • 【软考程序员学习笔记】——数据结构与算法基础

    目录  🍊一、数据结构概念和分类 🍊二、数组特点存储方式 🍊三、矩阵 特殊矩阵 非特殊矩阵 🍊四、栈和队列 🍊 五、二叉树的性质 🍊六、二叉树的遍历 (1)前序遍历(先根遍历,先序遍历) (2)中遍历(中根遍历) (3)后序遍历(后根遍历,后序遍历) 🍊七、二叉排序树 🍊八、

    2024年02月12日
    浏览(62)
  • 【零基础】学python数据结构与算法笔记14-动态规划

    学习python数据结构与算法,学习常用的算法, b站学习链接 动态规划在基因测序、基因比对、hmm 有应用场景。 从斐波那契数列看动态规划 练习: 使用递归和非递归的方法来求解斐波那契数列。 这种非递归求斐波那契数,可以看成是一个动态规划思想,每次都会把重复子问

    2023年04月09日
    浏览(45)
  • 读程序员的制胜技笔记02_算法与数据结构

    3.1.1.1. 根据你的需要,可以有更智能的算法 3.1.3.1. 算法本身并不意味着它很聪明 3.2.1.1. public static bool Contains(int[] array, int lookFor) { for (int n = 0; n < array.Length; n++) {        if (array[n] == lookFor) {            return true;        }    }    return false; } 3.3.1.1. public sta

    2024年02月06日
    浏览(62)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包