精华内容
下载资源
问答
  • 滑动窗口算法的分布式窗口限速的Golang实现。 安装$ go get -u github.com/RussellLuo/slidingwindow设计slidewindow是t slidewindowow的一种实现,Golang是滑动窗口算法的一种实现,用于分布式速率限制。 安装$ go ...
  • 滑动窗口算法

    千次阅读 多人点赞 2019-07-13 22:02:14
    什么是滑动窗口算法 我们学习过计算机网络都知道为了避免拥塞发生,在网络传输时有滑动窗口协议控制传输时流量。该协议允许发送方在停止并等待确认前发送多个数据分组。由于发送方不必每发一个分组就停下来等待确认...

    什么是滑动窗口算法

    我们学习过计算机网络都知道为了避免拥塞发生,在网络传输时有滑动窗口协议控制传输时流量。该协议允许发送方在停止并等待确认前发送多个数据分组。由于发送方不必每发一个分组就停下来等待确认,因此该协议可以加速数据的传输,提高网络吞吐量。这个跟我们今天说的滑动窗口算法是一个原理。

    滑动窗口算法的作用

    该算法的作用就是将我们多层嵌套的循环语句根据局部最优解来转换为单个的循环语句,从而减少时间复杂性。

    下面我们通过LeetCode 上的一道题来看看滑动窗口究竟该如何使用

    题目

    给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

    示例 1:

    输入: “abcabcbb”
    输出: 3
    解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。

    示例 2:

    输入: “bbbbb”
    输出: 1
    解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。

    示例 3:

    输入: “pwwkew”
    输出: 3
    解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
    请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。

    分析

    这道题目我们需要找到字符串中的最长的子串,普通的暴力解法是通过for循环遍历给定字符串的所有子串,判断子串中有没有重复的字符,如果没有则找出最长的。

    但是上面的算法我们时间复杂度为O(n^3)。那么有没有更好的算法呢,当然是有的,那就是滑动窗口算法。通过使用HashSet作为滑动窗口,我们可以用O(1)的时间来完成对字符是否在当前的子字符串中的检查。

    滑动窗口是数组/字符串问题中常用的抽象概念。窗口通常是在数组/字符串中由开始和结束索引定义的一系列元素的集合,即[left,right)(左闭,右开)。而滑动窗口是可以将两个边界向某一方向“滑动”的窗口。例如,我们将[left,right)向右滑动1个元素,则它将变为[left+1,right+1)(左闭,右开)。我们使用HashSet将字符存储在当前窗口[left,right)(最初left=right)中。然后我们向右侧滑动索引right,如果它不在HashSet中,我们会继续滑动 right。直到s[right]已经存在于HashSet中。此时,我们找到的没有重复字符的最长子字符串将会以索引left开头。如果我们对所有的leift这样做,就可以得到答案。

        public int lengthOfLongestSubstring(String s) {
            int n = s.length();
            Set<Character> set = new HashSet<>();
            int ans = 0, left = 0, right = 0;
            while (left < n && right < n) {
                if (!set.contains(s.charAt(right))){
                    set.add(s.charAt(right++));
                    ans = Math.max(ans, right - left);
                }
                else {
                    set.remove(s.charAt(left++));
                }
            }
            return ans;
        }
    

    算法分析

    这里时间复杂度为 O(2n)=O(n),空间复杂度为O(min(m,n))。

    优化

    这里我们还可以将算法优化,将字符串中每个字符和索引形成映射关系。举个例子,给定字符串“abcabcbb”,这里我们依次按照上述算法执行,我们到第四个字符也就是right为3时,我们left可以跳过前面的0123,直接left和right为4,从4开始再继续找。

        public int lengthOfLongestSubstring(String s) {
           int length = s.length();
           HashMap<Character,Integer> map = new HashMap<Character, Integer>();
           int ans =0;
           for(int left = 0,right = 0; left < length && right < length;right++){
               if (map.containsKey(s.charAt(right))){
                   left= Math.max(map.get(s.charAt(right)),left);
               }
               ans = Math.max(ans,right-left+1);
               map.put(s.charAt(right),right+1);
           }
           return ans;
       }
    

    总结

    从上面的解题我们可以明显的发现,滑动窗口算法的的时间复杂度为线性的(O(n)),我们可以用此算法来查找最大/最小k-子序列,XOR,乘积,总和等一些列问题。

    参考资料

    无重复字符的最长子串

    展开全文
  • MATALB可调用的图像滑动窗口算法,用mex编译后可调用。返回滑动窗口得到的图片块样本。
  • 本文借助IOS智能设备采集数据,建立相应的特征向量,提出基于支持向量机的车辆换道行为识别模型,其中针对连续换道行为的识别进一步提出一种改进的N-δ滑动窗口截取算法,用于对包含多个行为的数据进行快速划分,...
  • 从零开始手写vio- 第5节滑动窗口第5节滑动窗口算法实践
  • 滑动窗口算法实现 C#

    2012-11-30 10:01:41
    The sliding window algorithm 的过程是,随着窗口的增大有效的近似轨迹也随之增长,直到近似轨迹与原始归轨迹的误差值超过指定的误差范围。
  • C++滑动窗口算法

    2021-02-05 10:11:17
    滑动窗口算法在一个特定大小的字符串或数组上进行操作,而不在整个字符串和数组上操作,这样就降低了问题的复杂度,从而也达到降低了循环的嵌套深度。 如下题 给你两个长度相同的字符串,s 和 t。 将 s 中的第 i 个...

    滑动窗口算法在一个特定大小的字符串或数组上进行操作,而不在整个字符串和数组上操作,这样就降低了问题的复杂度,从而也达到降低了循环的嵌套深度。

    如下题

    给你两个长度相同的字符串,s 和 t。
    将 s 中的第 i 个字符变到 t 中的第 i 个字符需要 |s[i] - t[i]| 的开销(开销可能为 0),也就是两个字符的
    ASCII 码值的差的绝对值。

    用于变更字符串的最大预算是 maxCost。在转化字符串时,总开销应当小于等于该预算,这也意味着字符串的转化可能是不完全的。

    如果你可以将 s 的子字符串转化为它在 t 中对应的子字符串,则返回可以转化的最大长度。

    如果 s 中没有子字符串可以转化成 t 中对应的子字符串,则返回 0。

    示例 1:

    输入:s = “abcd”, t = “bcdf”, cost = 3 输出:3 解释:s 中的 “abc” 可以变为 “bcd”。开销为
    3,所以最大长度为 3。 示例 2:

    输入:s = “abcd”, t = “cdef”, cost = 3 输出:1 解释:s 中的任一字符要想变成 t
    中对应的字符,其开销都是 2。因此,最大长度为 1。 示例 3:

    字符串s字符串t开销最大长度
    [a] b c d[b] c d f11
    [a b] c d[b c] d f22
    [a b c] d[b c d] f33
    a [b c d]b [c d f]43

    只需要返回窗口的大小就是该开销可以转化的最大长度

    代码如下

    class Solution {
    public:
        int equalSubstring(string s, string t, int maxCost) 
        {
            int left = 0;   // 窗口左边界
            int cost = 0;   // 当前窗口消耗
            // i作为窗口右边界
            for (int i = 0; i < s.size(); i++)
            {
                cost += std::abs(s[i] - t[i]);
                // 如果当前窗口消耗大于总开销,则左边界++,缩减窗口
                if (cost > maxCost)
                {
                    cost -= std::abs(s[left] - t[left]);
                    left++;
                }
            }
            return s.size() - left;
        }
    };
    
    展开全文
  • 滑动窗口算法(思想)

    千次阅读 2019-12-20 20:09:13
    滑动窗口算法(思想) 题目: 输入: "abcabcbb"输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。 子串和串中字符的对比,只要出现相同字符都算重复,肯定要用到嵌套循环。如果暴力枚举,每个...

    滑动窗口算法(思想)

    题目:

    输入: "abcabcbb"
    输出: 3
    解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

    子串和串中字符的对比,只要出现相同字符都算重复,肯定要用到嵌套循环。如果暴力枚举,每个长度的子串都拿出来做自检,时间复杂度会比较高。使用滑动窗口的思想,对错误信息进行合理利用,可以有效减少执行次数。

    C语言解法:

    int lengthOfLongestSubstring(char * s){     
        int i = 0, j = 0;     int maxlen = 0;     int curlen = 0;     
        int len = strlen(s);     
        if (len == 0)         return 0;     
        for (; j < len && len - i > maxlen; j++) {         
            curlen++;         
            for (int k = i; k <= j; k++) {             
                if (s[k] == s[j + 1]) {                 
                    if (curlen > maxlen)                     maxlen = curlen; 
                    i = k + 1;                 
                    curlen = j - i + 1;                 
                    break;             
                }         
            }     
        }         
        if (curlen > maxlen)         return curlen;     
        else         return maxlen; 
    }

    滑动窗口初听觉得抽象模糊,其实拿卷尺一对比很好理解
    一个字符串,要在里面找出最长且没有重复字符的子串,就像拿着卷尺在上面不停地缩拉测量
    子串就是这个卷尺的伸出部分,即一个窗口,左边缩进,右边拉出
    因为不能有重复的字符,在右端逐渐拉长的过程中,每新增加的一个新字符都要拿来和左侧子串中的字符做对比
    在上面的程序里,用 i 指向卷尺头部,用 j 指向卷尺尾部,k 则作为子串中字符的索引
    每次对比开始时,用 i 的值初始化 k,当找到重复字符时,又将 k + 1的值赋给 i,即直接将窗口的左侧移动到重复字符的下一个字符位置
    与枚举法相比,由于利用了子串中重复字符的位置,直接将窗口左侧跳到该字符的下一个位置,每次检查出重复减少了 k - i 个子串的自检

    题目

    给定数组,获取数组中n个连续元素最大的和

    C语言解法:

    int maxSumSub(nums, n) { 
        int len = (int) sizeof(nums) / sizeof(int);  
        int maxsum = 0; 
        if (n > len) {  return 0;   }  
        for (int i = 0; i < n; i++) {  maxsum += nums[i];    } 
        int windowsum = maxsum; 
        for (int i = n; i < len; i++) {
            windowsum += nums[i] - nums[i - n]; 
            if (windowsum > maxsum)  maxsum = windowsum; 
       } 
        return maxsum; 
    }

    如果用滑动窗口法,基本思想是,每次向右滑动时,窗口右侧进入的新元素减去左侧退出的旧元素,得到的结果与上次的和相加得到新的和
    这样做的巧妙之处在于,无论题设n有多大,每次窗口移动后,计算新和,只需将窗口两端进出的新旧元素相减,得到的结果与旧和相加就可以得到新和
    总结
    上述两个题目,分别用到了动态滑动窗口和固定滑动窗口,即在滑动时长度变化和不变的两种窗口
    可以看到,滑动窗口的应用场景有几个特点:
    1. 需要输出或比较的结果在原数据结构中是连续排列的(字符串中的连续不重复子串,数组中的连续元素最大和)
    2. 每次窗口滑动时,只需观察窗口两端元素的变化,无论窗口多长,每次只操作两个头尾元素,当用到的窗口比较长时,可以显著减少操作次数
    3. 窗口内元素的整体性比较强,窗口滑动可以只通过操作头尾两个位置的变化实现,但对比结果时往往要用到窗口中所有元素(检查窗口中是否含有重复字符,对比窗口中元素的和)

    展开全文
  • 这里写目录标题Sentinel的限流原理滑动时间窗口算法 Sentinel的限流原理 限流效果,对应有DefaultController快速失败 WarmUpController慢启动(令牌桶算法) RateLimiterController(漏桶算法) 滑动时间窗口算法 ...

    Sentinel限流及其滑动窗口算法

    Sentinel的限流原理

    限流效果,对应有DefaultController快速失败

    WarmUpController慢启动(令牌桶算法)

    RateLimiterController(漏桶算法)

    滑动时间窗口算法

    1. 固定时间窗口算法
      即比如每一秒作为一个固定的时间窗口,在一秒内最多可以通过100个请求,那么在统计数据的时候,如果0-500ms没有请求,而500-1000ms有100个请求,那么这一百个请求都能通过,在1000-1500ms的时候,又有100个请求过来了,它依然能够通过,因为在1000ms的时候又开启了一个新的固定时间窗口。这样,500-1500ms这一秒内有了200个请求,但是它依然能够通过,所以这就会造成数据统计的不准确性,并不能保证在任意的一秒内都使得通过请求数小于100,。
    2. 普通的滑动窗口做法
      因为固定时间窗口带来的数据同的不准确性,就会造成可能局部的时间压力过高,所以就需要采用滑动窗口算法来进行统计,滑动窗口时间算法意思就是,从请求过来的时刻开始,统计往前一秒中的数据,通过这个数据来判断是否进行限流等操作。这样的话准确性就会有很大的提升,但是由于每一次请求过来都需要重新统计前一秒的数据,就会造成巨大的性能损失。所以这也是他的不合理的地方。
    3. Sentinel的滑动时间窗口算法
      由于固定时间窗口带来的不准确性和普通滑动窗口带来的性能损失的缺点,所以Sentinel对这两种方案采取了折中的方案。
      在Sentinel中会将原本的固定的时间窗口划分成很多更小的样本窗口,每一次请求的数据都会被保存在小的样本窗口中去,而每一次获取的时候都会去获取这些样本时间窗口中的数据,从而不需要进行重新统计,就减小了性能损耗,同时时间窗口被细粒度化了,不准确性也会降低很多。

    在统计插槽StatisticsSlot类中有ArrayMetric的类的成员变量,用于统操作和获取统计数据,而ArrayMetric类有一个成员变量LeapArray data,并提供了一些操作这个成员变量data信息的方法。

    LeapArray提供两个参数sampleCount 样本数量,intervalInMs 间隔时间,意思就是在这一段的间隔时间内,被分成了sampleCount 个样本去分别进行统计,默认间隔时间是1s,sampleCount 是2。

    下面看看LeapArray的一部分源码,它也是实现滑动窗口最为重要的地方。

    public abstract class LeapArray<T> {
        //每一个样本窗口的时间长度
        protected int windowLengthInMs;
        //一个滑动窗口被划分成了多少个样本
        protected int sampleCount;
        //时间窗口的时间长度
        protected int intervalInMs;
        private double intervalInSecond;
        //一个样本窗口数组,将一个滑动窗口划分为sampleCount个样本窗口的数组
        protected final AtomicReferenceArray<WindowWrap<T>> array;
        //部分代码省略
    }
    

    在LeapArray有这几个成员变量:

    1. 每一个样本窗口的时间长度
    2. 一个滑动窗口被划分成的样本数量
    3. 滑动时间窗口的时间长度
    4. 样本窗口数组
        public WindowWrap<T> currentWindow(long timeMillis) {
            if (timeMillis < 0) {
                return null;
            }
            //计算当前样本窗口的在array中的索引,以当前时间除以样本时间长度,获得timeId
            //再将TimeId对数组长度取余,得到索引,这就相当于把array当做了一个样本窗口圆环,就像官网上的图一样
            int idx = calculateTimeIdx(timeMillis);
            // 计算当前时间的样本窗口的开始时间
            long windowStart = calculateWindowStart(timeMillis);
            while (true) {
                WindowWrap<T> old = array.get(idx);
                if (old == null) {
                //如果原来这个位置的样本窗口就是null的,就说明以前还没有网array的这个位置放过样本窗口,
                // 这时就新建一个样本窗口用cas操作放到数组的这个位置,并返回该窗口
                    WindowWrap<T> window = new WindowWrap<T>(windowLengthInMs, windowStart, newEmptyBucket(timeMillis));
                    if (array.compareAndSet(idx, null, window)) {
                        // Successfully updated, return the created bucket.
                        return window;
                    } else {
                        // Contention failed, the thread will yield its time slice to wait for bucket available.
                        Thread.yield();
                    }
                } else if (windowStart == old.windowStart()) {
                    //如果计算出来的窗口开始时间和现在存在的这个串口开始时间是一样的,就说明目前正处于这个样本窗口的时间内
                    //直接返回当前样本窗口
                    return old;
                } else if (windowStart > old.windowStart()) {
                    //如果计算出来的窗口开始时间大于现在存在的样本窗口开始时间,就说明现存的样本窗口已经过时了
                    //这边相当于在array数组圆环上不断旋转着设置新的样本窗口,要去生成新的样本窗口把以前的老的给覆盖了
                    if (updateLock.tryLock()) {
                        try {
                            // 获取到锁,再去覆盖样本窗口,防止并发更新问题
                            return resetWindowTo(old, windowStart);
                        } finally {
                            updateLock.unlock();
                        }
                    } else {
                        // 没有获取到就让出cpu一小段时间再回去重新尝试获取锁
                        Thread.yield();
                    }
                } else if (windowStart < old.windowStart()) {
                    // Should not go through here, as the provided time is already behind.
                    return new WindowWrap<T>(windowLengthInMs, windowStart, newEmptyBucket(timeMillis));
                }
            }
        }
    

    LeapArray中有一个currentWindow方法,用于获取当前样本窗口,它的逻辑是这样的:

    1. 计算当前样本窗口的在array中的索引,以当前时间除以样本时间长度,获得timeId
    2. 再将TimeId对数组长度取余,得到索引,这就相当于把array当做了一个样本窗口圆环,就像官网上的图一样,这样所有的时间窗口都会在这个数组里进行循环。
    3. 获取当前时间所对应的样本窗口开始时间,与目前数组中的样本窗口进行比较。
    4. 如果数组最终该索引不存在样本窗口,就创建一个样本窗口放到数组中
    5. 如果计算出来的窗口开始时间和现在存在的这个串口开始时间是一样的,就说明目前正处于这个样本窗口的时间内,直接返回该窗口就好了
    6. 如果计算出来的窗口开始时间大于现在存在的样本窗口开始时间,就说明现存的样本窗口已经过时了,需要重新覆盖一个新的样本窗口

    在LeapArray里,最重要的就是这个样本窗口数组,它将一个完整的滑动时间窗口划分成了sampleCount个样本窗口WindowWrap,而样本窗口WindowWrap的结构如下:

    public class WindowWrap<T> {
    
        /**
         * Time length of a single window bucket in milliseconds.
         */
        //该样本窗口的长度
        private final long windowLengthInMs;
    
        /**
         * Start timestamp of the window in milliseconds.
         */
        //该样本窗口开始的时间
        private long windowStart;
    
        /**
         * Statistic data.
         */
        //每一个样本窗口里统计的数据都存在这儿
        private T value;
        
        /**
         * 其余代码省略
         */
    }
    

    每一个样本窗口都包含了三个数据:

    1. 该样本窗口的时间长度
    2. 该样本窗口开始的时间
    3. 每一个样本窗口里统计的数据

    这就是滑动窗口的原理,而每次需要对统计数据做操作的时候,就会获取当前滑动窗口的样本窗口,并对样本窗口里面的数据进行操作。简单的示范一下调用的一个流程:

    • 首先统计数据,直接可以去看StatisticSlot插槽,因为这个插槽本身就是做这个统计数据相关的事情的
        @Override
        public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count,
                          boolean prioritized, Object... args) throws Throwable {
            try {
                // Do some checking.
                //会一层一层的去执行完所有的slot规则检查
                fireEntry(context, resourceWrapper, node, count, prioritized, args);
                // Request passed, add thread count and pass count.
                //如果到这里了就说明规则检查圈通过了,可以做成功的统计了
                //添加成功的线程数
                node.increaseThreadNum();
                //添加成功通过的请求数量
                node.addPassRequest(count);
                if (context.getCurEntry().getOriginNode() != null) {
                    // Add count for origin node.
                    context.getCurEntry().getOriginNode().increaseThreadNum();
                    context.getCurEntry().getOriginNode().addPassRequest(count);
                }
                if (resourceWrapper.getEntryType() == EntryType.IN) {
                    // Add count for global inbound entry node for global statistics.
                    //一个资源对应一个ClusterNode,给他添加全局的统计
                    Constants.ENTRY_NODE.increaseThreadNum();
                    Constants.ENTRY_NODE.addPassRequest(count);
                }
    
                // Handle pass event with registered entry callback handlers.
                for (ProcessorSlotEntryCallback<DefaultNode> handler : StatisticSlotCallbackRegistry.getEntryCallbacks()) {
                    handler.onPass(context, resourceWrapper, node, count, args);
                }
            } catch (PriorityWaitException ex) {
                node.increaseThreadNum();
                if (context.getCurEntry().getOriginNode() != null) {
                    // Add count for origin node.
                    context.getCurEntry().getOriginNode().increaseThreadNum();
                }
                if (resourceWrapper.getEntryType() == EntryType.IN) {
                    // Add count for global inbound entry node for global statistics.
                    Constants.ENTRY_NODE.increaseThreadNum();
                }
                // Handle pass event with registered entry callback handlers.
                for (ProcessorSlotEntryCallback<DefaultNode> handler : StatisticSlotCallbackRegistry.getEntryCallbacks()) {
                    handler.onPass(context, resourceWrapper, node, count, args);
                }
            } catch (BlockException e) {
                //添加被Block的线程和请求数量的相关统计
                context.getCurEntry().setBlockError(e);
                // 添加被阻塞数量
                node.increaseBlockQps(count);
                if (context.getCurEntry().getOriginNode() != null) {
                    context.getCurEntry().getOriginNode().increaseBlockQps(count);
                }
                if (resourceWrapper.getEntryType() == EntryType.IN) {
                    // Add count for global inbound entry node for global statistics.
                    Constants.ENTRY_NODE.increaseBlockQps(count);
                }
                // Handle block event with registered entry callback handlers.
                for (ProcessorSlotEntryCallback<DefaultNode> handler : StatisticSlotCallbackRegistry.getEntryCallbacks()) {
                    handler.onBlocked(e, context, resourceWrapper, node, count, args);
                }
                throw e;
            } catch (Throwable e) {
                // Unexpected internal error, set error to current entry.
                context.getCurEntry().setError(e);
                throw e;
            }
        }
    

    在StatisticSlot的Entry方法中,就会添加成功的数量统计,或者根据各种不同的异常,添加不同的数据统计,如请求成功通过的话,就会调用node.addPassRequest(count),而它最后会去调用ArrayMetric类的addPass方法,获取当前的样本时间窗口,并在当前的样本时间窗口上进行数据统计操作。

        @Override
        public void addPass(int count) {
            //获取当前样本窗口,在它上面添加一个成功的统计
            WindowWrap<MetricBucket> wrap = data.currentWindow();
            wrap.value().addPass(count);
        }
    
    展开全文
  • 滑动窗口
  • 滑动窗口算法总结

    千次阅读 2020-08-12 18:55:00
    应用滑动窗口技术: 我们使用线性循环计算n个项中前k个元素的总和,并将总和存储在变量window_sum中。 然后,我们将在阵列上线性滑动直至达到最终并同时追踪最大和。 要获得k个元素块的当前总和,只需从前一个块中...
  • 在力扣常用解题法中,我们常常会看到这些: 滑动窗口 双指针 快慢指针/ 链表题目 原地链表翻转 区间合并 ...而偏偏是最常用的,也排在首位的滑动窗口算法,却并不为人熟知,什么是滑动窗口算法呢?? .
  • 滑动窗口算法(C语言版讲解) 滑动窗口算法主要用于解决字符串查找对应排序的题型。 算法的基本思路 1.辅助算法 :快慢指针 由于要运用快慢指针的思想,这里读者需要先了解快慢指针。 typedef struct node{ int ...
  • 滑动窗口算法技巧【Python】

    千次阅读 2020-06-30 22:39:06
    这篇文章通过几道题目来总结滑动窗口算法的解题模板与技巧。 直接给出滑动窗口解题的模板 left, right = 0, 0 win = [] while right < len(s): win.append(s[right]) right += 1 while isValid(win): win....
  • 滑动窗口算法学习

    万次阅读 2019-05-14 12:05:36
    最近做了几道有关滑动窗口算法,在此总结一下。 滑动窗口 就像描述的那样,可以理解成是一个会滑动的窗口,每次记录下窗口的状态,再找出符合条件的适合的窗口 可以使用滑动窗口来减少时间复杂度 经典滑动窗口...
  • 滑动窗口算法思想图解说明

    千次阅读 2021-02-21 12:48:21
    滑动窗口算法 滑窗思想在解决一些联系子数组问题上被广泛应用,遇到对一些给定长度的子数组序列进行操作 或者求解子串问题,首先想到滑窗技巧 滑窗思想模板 最为经典的滑窗算法有其固定的解题模板 下面就通过...
  • 原文地址:滑动窗口算法基本原理与实践 目录 滑动窗口算法(Sliding Window Algorithm) 基本示例 滑动窗口法的大体框架 算法实例 1208. 尽可能使字符串相等 代码 239. 滑动窗口最大值 解答: 1456. 定长...
  • 滑动窗口算法(Sliding Window Algorithm)

    万次阅读 多人点赞 2019-03-05 16:48:40
    滑动窗口算法(Sliding Window Algorithm) Sliding window algorithm is used to perform required operation on specific window size of given large buffer or array. This technique shows how a nested for...
  • TCP的滑动窗口算法

    千次阅读 2019-07-25 14:17:36
    它本质上是描述接收方的TCP数据报缓冲区大小的数据,发送方根据这个数据来计算自己最多能发送多长的数据,如果发送方收到接收方的窗口大小为0的TCP数据报,那么发送方将停止发送数据,等到接收方发送窗口大小不为0...
  • 滑动窗口算法(`Sliding Window Algorithm`)是常见的一种算法:它思想简洁且功能强大,可以用来解决一些查找满足一定条件的**连续区间**的性质/长度的问题。由于区间连续,因此当区间发生变化时,可以通过旧有的计算...
  • length = max(max_length, window_end-window_start + 1) return max_length 4 思考总结 如果大家看了前道题和本题,应该会有个感觉,滑动窗口算法,其实就是将原来的暴力算法进行了优化而已。主要的优化点其实有两...
  • 【C语言】滑动窗口算法

    千次阅读 多人点赞 2020-05-16 23:59:09
    1.滑动窗口的思想: 它是一个运行在一个大数组上的子列表,该数组是一个底层元素集合。假设有数组 [a b c d e f g h ],一个大小为 3 的 滑动窗口 在其上滑动,则有: [a b c]  [b c d]    [c d e]      [d e ...
  • 最开始想的是要暴力破解,写出了复杂度o(n²)的解法,不太满意,看了题解发现了滑动窗口这种算法,豁然开朗 先上代码 复杂度只有o(n) 思路就是我们定义一个map数据结构,通过不停的计算子串的起始位置和结束位置来...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 52,326
精华内容 20,930
关键字:

滑动窗口算法