算法整理-3滑动窗口

  • 什么是滑动窗口

    在数组上维护一个 [ , ) 左闭右开可滑动的东西
    滑动数组

  • 滑动窗口的构建

    static String minWindow(String s,String t){
        char[] ss = s.toCharArray();
        HashMap<Character,Integer> need = new HashMap<>();
        HashMap<Character,Integer> window = new HashMap<>();
        int left = 0, right = 0;
        int valid = 0;
        // 记录最⼩覆盖⼦串的起始索引及⻓度
        int start = 0, len = Integer.MAX_VALUE;
        //need哈希表代表需要的字母和对应的个数
        for (char c: t.toCharArray()){
            need.put(c,need.getOrDefault(c,0)+1);
        }
        while (right < ss.length){
        	// c 是将移⼊窗⼝的字符
            char c = ss[right];
            // 右移窗口
            right++;
            //一系列更新操作
            if (need.containsKey(c)){
                window.put(c,window.getOrDefault(c,0)+1);
                if (need.get(c) == window.get(c))
                    valid ++ ;
            }
            //判断何时左边进行收缩
            while (valid == need.size()){
           		// 在这⾥更新最⼩覆盖⼦串
                if (right - left < len){
                    start = left;
                    len = right - left;
                }
                char d = ss[left];
                left ++;
                //一系列更新操作
                if (need.containsKey(d)){
                    if (window.get(d) == need.get(d))
                        valid--;
                    window.put(d,window.get(d)-1);
                }
            }
        }
        return len==Integer.MAX_VALUE? "":s.substring(start,start+len);
    }
  • 滑动窗口的应用
    Leetcode
    1. 最⼩覆盖⼦串(困难)
    2. 字符串的排列(中等)
    3. 找到字符串中所有字⺟异位词(中等)
    4. ⽆重复字符的最⻓⼦串(中等)
<think>好的,我现在需要帮助用户理解令牌桶算法滑动窗口算法的工作原理、实现方式、应用场景以及它们的对比分析。用户还提到了相关的引用内容,需要结合这些引用信息来组织回答。 首先,我需要回忆这两个算法的基本概念。令牌桶算法主要用于流量控制,通过定期向桶中添加令牌来允许请求的处理,当请求需要处理时,必须从桶中获取令牌。如果桶中没有足够的令牌,请求就会被限制。引用[3]中提到,令牌桶每秒钟会添加令牌,当桶里没有令牌时,超出的流量会被处理,这可能涉及到速率限制的具体实现。 接下来是滑动窗口算法。根据引用[1]和[2],计数器算法其实是滑动窗口算法一个特例,当窗口没有细分时,就是计数器算法滑动窗口将时间划分为更细的格子,比如多个时间片,这样可以更精确地控制请求速率,避免计数器算法的临界问题。例如,一个时间窗口被分成多个小窗口,每个小窗口维护自己的计数器,整体窗口的计数是这些小窗口的总和,随着时间推移,旧的小窗口会被移除,新的被添加,从而实现滑动效果。 然后,我需要整理这两个算法的工作原理和实现方式。令牌桶的实现可能需要一个定时器来定期添加令牌,同时维护当前可用的令牌数量。而滑动窗口则需要维护一个时间线,记录每个时间片的请求数,并在时间推移时更新窗口。引用[4]提到的双速率三色标记算法可能与流量标记有关,但可能不直接关联,暂时可以忽略,除非用户的问题涉及到流量标记的具体应用。 应用场景方面,令牌桶常用于网络流量整形和API速率限制,因为它允许突发流量,只要桶中有足够的令牌。滑动窗口则更适合需要精确控制单时间内请求数量的场景,比如实时系统的请求限制,避免计数器算法的临界问题。 对比分析时,需要指出令牌桶的突发处理能力和滑动窗口的平滑控制特点。令牌桶在桶满时可以处理突发请求,而滑动窗口则通过细分时间窗口来更均匀地分布请求,避免瞬间的高峰。 现在需要确保回答结构清晰,分点说明每个算法的工作原理、实现、应用,然后对比分析。同时要正确引用用户提供的参考文献,比如引用[1]和[2]说明滑动窗口与计数器的关系,引用[3]解释令牌桶的工作机制。 还要注意用户提到的系统级指令,比如数学公式用$...$,独立公式用$$...$$,但用户的问题可能不涉及太多数学公式,但如果有的话需要正确应用。例如,令牌桶的令牌生成速率可以用公式表示,如$r$ tokens/sec,最大桶容量$B$,这样请求需要消耗令牌,可以用数学表达式描述。 最后生成相关问题,需要根据内容提出,比如两种算法的优缺点比较,如何选择适合的算法,或者具体实现中的细节问题。</think>### 令牌桶算法滑动窗口算法对比分析 #### 一、令牌桶算法 1. **工作原理** 令牌桶算法通过周期性向“桶”中添加令牌(token)实现流量控制。桶容量上限为$B$,每秒钟新增$r$个令牌[^3]。当请求到达时: - 若桶中有足够令牌,则消耗对应数量令牌,请求被放行 - 若令牌不足,则触发限流策略(如丢弃/排队请求) 2. **实现方式** ```python class TokenBucket: def __init__(self, rate, capacity): self.rate = rate # 令牌生成速率(tokens/s) self.capacity = capacity # 桶容量 self.tokens = 0 # 当前令牌数 self.last_time = time.time() def consume(self, tokens_needed): now = time.time() elapsed = now - self.last_time self.tokens = min(self.capacity, self.tokens + elapsed * self.rate) # 补充令牌 self.last_time = now if self.tokens >= tokens_needed: self.tokens -= tokens_needed return True return False ``` 3. **应用场景** - 网络流量整形(允许突发流量) - API调用速率限制(如GitHub API每分钟5000次请求) - 分布式系统流量均衡 #### 二、滑动窗口算法 1. **工作原理** 将时间划分为$N$个细粒度窗口(如1分钟拆分为60个1秒窗口),维护每个小窗口的请求计数。随时间推移动态滑动窗口范围,总请求数不超过窗口容量$W$时允许通过[^1][^2]。 $$ \sum_{i=1}^{N} C_i \leq W $$ ($C_i$表示第$i$个小窗口的请求数) 2. **实现方式** ```python class SlidingWindow: def __init__(self, window_size, max_requests): self.window = deque() # 存储时间戳的队列 self.window_size = window_size # 时间窗口长度(秒) self.max_requests = max_requests # 最大请求数 def allow_request(self): now = time.time() # 移除过期时间戳 while self.window and self.window[0] < now - self.window_size: self.window.popleft() if len(self.window) < self.max_requests: self.window.append(now) return True return False ``` 3. **应用场景** - 实时系统请求限流(如支付系统) - 防止计数器算法的临界问题(如00:59-01:01的瞬时高峰) - 分布式监控系统数据采集 #### 三、算法对比分析 | 特性 | 令牌桶算法 | 滑动窗口算法 | |---------------------|-----------------------------------|-----------------------------------| | **突发处理** | 允许突发(桶容量内) | 严格限制窗口内总量 | | **时间精度** | 依赖定时器精度 | 依赖窗口划分粒度 | | **实现复杂度** | 中等(需处理并发竞争) | 较高(需维护时间窗口队列) | | **典型应用** | 网络流量整形、CDN限速 | API网关限流、交易系统风控 | | **资源消耗** | 内存消耗低(仅存储令牌数) | 内存较高(需存储时间戳队列) | #### 四、选择建议 - 需要**容忍突发流量**时选择令牌桶(如视频流传输) - 要求**严格平均速率**时选择滑动窗口(如秒杀系统) - 高并发场景可结合两种算法(如外层滑动窗口+内层令牌桶)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值