首页 > 其他分享 >细聊滑动窗口

细聊滑动窗口

时间:2024-10-20 21:09:44浏览次数:7  
标签:窗口 word len 单词 words 滑动 细聊 left

前段时间忙于写系列文章,怒刷算法题的进度算是耽误了不少。刚好遇到了一道需要滑动窗口的题目,做完之后觉得挺有意思,有必要好好聊一下滑动窗口。
所谓滑动窗口(slide window)是一种优化算法的抽象概念,主要于解决数组、字符串等线性结构中的子数组或子序列问题。它的整个思路是通过维护一个窗口(window)在数组上滑动,每次滑动一个单元距离,从而减少重复计算。
滑动窗口一般分为2种:

固定大小窗口:窗口的大小是固定的,通过移动窗口在数组或字符串上的位置来解决问题。例如:求数组种固定长度子数组的最大和。

可变大小窗口:根据条件动态增大或者缩小窗口。例如:求不超过给定和的最大子数组。

对于固定大小窗口问题,最典型的就是leetCode第三十题:

给定一个字符串 s 和一个包含多个长度相同的单词的数组 words,要求找出 s 中所有的起始索引,这些起始索引所对应的子串正好是 words 中所有单词的串联排列顺序不限定,但每个单词必须用一次)。

示例:

输入:
s = "barfoothefoobarman"
words = ["foo", "bar"]

输出:
[0, 9]

解释:
从索引 0 的子串是 "barfoo",它是 ["foo", "bar"] 的串联。
从索引 9 的子串是 "foobar",它也是 ["foo", "bar"] 的串联。

利用滑动窗口,可以很容易实现如下代码:

from collections import Counter
from typing import List

class Solution:
    def findSubstring(self, s: str, words: List[str]) -> List[int]:
        if not s or not words:
            return []

        word_len = len(words[0])
        word_count = len(words)
        total_len = word_len * word_count
        word_freq = Counter(words)
        result = []

        # 只遍历 word_len 次
        for i in range(word_len):
            left = i
            right = i
            seen = Counter()
            matched_count = 0

            while right + word_len <= len(s):
                # 提取当前单词
                word = s[right:right + word_len]
                right += word_len

                if word in word_freq:
                    seen[word] += 1
                    matched_count += 1

                    # 如果当前单词出现次数超过了预期,移动左指针
                    while seen[word] > word_freq[word]:
                        left_word = s[left:left + word_len]
                        seen[left_word] -= 1
                        matched_count -= 1
                        left += word_len

                    # 如果匹配的单词数量等于 words 中的单词数量,记录起始索引
                    if matched_count == word_count:
                        result.append(left)
                else:
                    # 当前单词不在 words 中,重置窗口
                    seen.clear()
                    matched_count = 0
                    left = right

        return result

在上述的代码中,定义了left和right两个指针,不断地移动left和right的位置,来让窗口中的字符串符合条件。当单词出现的频率大于预期的数量,则把left变量向右移动一个单词长度(word_len),并且减少seen变量中对应单词的数量,同时减少matched_count。

当遇到不在规定中的单词,则重置整个窗口。

这里第一个循环比较取巧,只循环单词长度(word_len)就能遍历出所有的不重复结果。

第二个例子是大小不固定的窗口案例,题目是:

求数组中和不超过 k 的最大长度子数组。

def get_max_sub_arry_length(nums: List[int], k: int) -> int:
    left = 0
    max_length = 0
    sum = 0
    for right in range(len(nums)):
        # 扩大窗口
        sum += nums[right]

        while sum > k and left <= right:
            # 缩小窗口
            sum -= nums[left]
            left += 1
        # 重新计算最大长度
        max_length = max(max_length, right - left + 1)
    
    return max_length

nums = [1,2,3,4,5]
k = 8
print(get_max_sub_arry_length(nums, k))

标签:窗口,word,len,单词,words,滑动,细聊,left
From: https://www.cnblogs.com/freephp/p/18487909

相关文章

  • 私钥碰撞器,单窗口月搜易可达1000+可无限放大
    功能介绍:协议私钥碰撞,24小时全自动挂机碰到自动建立文档储存运气好每天几十几百个U甚至更多运气不好也有好几个U有保底双协议bnb和eth,btc待发布设备需求:电脑......
  • DELPHI 隐藏程序窗口,以及TListView控件,点击标题进行排序
    设置视图: 运行效果:    unitHideWindown;interfaceusesWindows,Messages,SysUtils,Classes,Forms,StdCtrls,ActiveX,ComObj,ShellAPI,Tlhelp32,Vcl.Controls,Vcl.ComCtrls,psapi,Vcl.ExtCtrls;typeTForm1=class(TForm)GetWList......
  • 【优选算法篇】踏入算法的深邃乐章:滑动窗口的极致探秘
    文章目录C++滑动窗口详解:进阶题解与思维分析前言第二章:进阶挑战2.1水果成篮解法一:滑动窗口解法二:滑动窗口+数组模拟哈希表复杂度分析:图解分析:示例:滑动窗口执行过程图解:详细说明:2.2找到字符串中所有字母异位词解法:滑动窗口+哈希表复杂度分析:图解分析:滑动窗口执......
  • MYSQL-窗口函数
    判断函数if(expr,v1,v2):表达式结果为true返回v1,否则返回v2ifnull(列名,dv):列值为null返回dv,否则返回列值.nullif(expr1,expr2):表达式1=表达式2返回null,不等于返回表达式1的值.窗口函数作用:可以为表新增一列,新增的列是什么取决于over()函数前面的函数.主......
  • 【优选算法篇】编织算法的流动诗篇:滑动窗口的轻盈之美
    文章目录C++滑动窗口详解:基础题解与思维分析前言第一章:热身练习1.1长度最小的子数组解法一(暴力求解)解法二(滑动窗口)滑动窗口的核心思想图解分析滑动窗口的有效性时间复杂度分析易错点提示1.2无重复字符的最长子串解法一(暴力求解)解法二(滑动窗口)图解分析详细说明:1.3......
  • Stats渲染数据统计窗口
    Statistics窗口,全称叫做RenderingStatisticsWindow,即渲染统计窗口(或渲染数据统计窗口),窗口中罗列出关于渲染、声音、网络状况等多种统计信息,下面详细的解释一下这些项的意义。FPS(TimeperframeandFPS)framesperseconds表示引擎处理和渲染一个游戏帧所花费的时间,该数字主......
  • LeetCode 209 - 长度最小的子数组(滑动窗口法)
    题目描述给定一个含有n个正整数的数组和一个正整数target,我们要找出该数组中满足其总和大于等于target的长度最小的子数组,即子数组[nums_left,nums_right],并返回其长度。如果不存在符合条件的子数组,返回0。解题思路我们可以使用滑动窗口解决这道问题。初始化左指针......
  • vecode写c++遇到窗口一闪而过+中文乱码咋办
    本人没使用系统cmd窗口,而是使用了vscode内置终端,目的是为了之后输出中文的时候不乱码(vscode是utf-8,cmd是gbk,干脆全部使用vscode,不使用系统cmd作为输出窗口)附上配置文件:launch.json{//使用IntelliSense了解相关属性。//悬停以查看现有属性的描述。//欲了解......
  • 滑动阻尼,惯性滚动列表,边界回弹,惯性回弹
    https://juejin.cn/post/7426280686695759882<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0">&......
  • flink中窗口和水位线-基于DataStream API
    文章目录前言Watermark的代码Window的代码实践前言在之前的文章中,有在FllinkSQL来实现窗口和水位线—flink中水位线和窗口的工作原理,这次使用DataStreamAPI的方式来实现窗口和水位线,主要代码来自尚硅谷的课件资料。Watermark的代码1.WatermarkStrategy.forBoun......