滑动窗口

滑动窗口(单调双端队列实现)

滑动窗口是想象出来的一种数据结构:

  • 滑动窗口有左边界L和右边界R
  • 在数组或字符串或一个序列上,记为S,窗口就是S[L…R]这一部分
  • R往右滑,意味着一个样本进了窗口,L往右滑意味着一个样本处了窗口
  • L和R只能往右滑
  • R往右 —> R++ —> 一个样本进了窗口
  • L往右 —> L++ —> 一个样本出窗口
  • L <= R
  • 双端队列中只放位置
  • 数据状况和问题本身建立单调性
/**
     * 给的一个数组arr,窗口大小为w,求每个窗口中的最大值
     *
     * @param arr
     * @param w
     * @return
     */
    public int[] slidwindow(int[] arr, int w) {
        if (arr == null || w < 1 || w < arr.length) {
            return null;
        }
        //其中放的是位置,头代表 (大->小)尾
        int[] res = new int[arr.length - w + 1];
        int index = 0;
        LinkedList<Integer> qmax = new LinkedList<>();
        // L...R
        // 当前让 R 进窗口
        for (int R = 0; R < arr.length; R++) {
            // R -> 值  可以放在比他大的数后,或者空
            // 当双端队列不为空的并且双端队列的最后一个数 <= arr[R] 的时候,弹出元素
            while (!qmax.isEmpty() && qmax.peekLast() <= arr[R]) {
                qmax.pollLast();
            }
            // arr[R]进队列
            qmax.addLast(arr[R]);
            // 如果窗口没有形成W的长度之前,不弹出数字的
            if (qmax.peekFirst() == R - w) {
                qmax.pollFirst();
            }
            // 以上窗口更新做完了,更新数组
            if (R >= w - 1) {
                res[index++] = arr[qmax.peekFirst()];
            }
        }
        return res;
    }
/**
     * LeetCode3. 无重复字符的最长子串
     * 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
     * <p>
     * 示例 1:
     * <p>
     * 输入: "abcabcbb"
     * 输出: 3
     * 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
     * <p>
     * 示例 2:
     * <p>
     * 输入: "bbbbb"
     * 输出: 1
     * 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
     * <p>
     * 示例 3:
     * <p>
     * 输入: "pwwkew"
     * 输出: 3
     * 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
     *      请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
     * <p>
     * 来源:力扣(LeetCode)
     * 链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters
     * 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
     *
     * @param s
     * @return
     */
    public int lengthOfLongestSubstring(String s) {
        if (s == null) {
            return 0;
        }
        char[] chars = s.toCharArray();
        int max = 0;
        int L = -1;
        Deque deque = new ArrayDeque();
        for (int R = 0; R < chars.length; R++) {
            //如果当前的窗口L位置不为0,则弹出当前位置的元素,进行尝试下一个位置
            if (R != 0) {
                deque.pollFirst();
            }
            // 判断当前窗口的右+1位置,是否存在于双端队列中,如果存在,说明重复,
            // 当前位置的不重复长度即为 双端对列中元素的个数
            while (L + 1 < chars.length && !deque.contains(chars[L + 1])) {
                deque.addLast(chars[L + 1]);
                L++;
            }
            //对比最大值
            max = max > deque.size() ? max : deque.size();
        }
        return max;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值