16数据结构与算法刷题之【滑动窗口】篇

简介: 16数据结构与算法刷题之【滑动窗口】篇

leetcode


3. 无重复字符的最长子串【中等】


学习:leetcode题解


题目链接:3. 无重复字符的最长子串


题目内容:


速记:抓住重点最长、子串,则表名我们要找到连续且无重复的,这时候我们就可以使用滑动窗口来进行解决。


①set版本,使用集合开销较大。


②数组版本,限定在0-128之间,开销相对于set小。


思路:


1、滑动窗口(set方式)


思路:题目要求是最长子串,那么一定是连续的子串。这里要是想要时间复杂度为O(n)就需要使用到滑动窗口,规则如下:
这里我直接拿leetcode官方的示例:
以(a)bcabcbb开始的最长字符串为(abc)abcbb;
以a(b)cabcbb开始的最长字符串为a(bca)bcbb;
以ab(c)abcbb开始的最长字符串为ab(cab)cbb;
以abc(a)bcbb开始的最长字符串为abc(abc)bb;
以abca(b)cbb开始的最长字符串为abca(bc)bb;
以abcab(c)bb开始的最长字符串为abcab(cb)b;
以abcabc(b)b开始的最长字符串为abcabc(b)b;
以abcabcb(b)开始的最长字符串为abcabcb(b)。
思路:每个区间我们可以使用set来进行暂存,每进行移动窗口,将左边的一位进行移除,窗口中的依旧在set集合里不动,之后再去依次添加之后没出现过的元素。


复杂度分析:时间复杂度O(n),空间复杂度O(∣Σ∣):O(∣Σ∣)指的是字符集的大小,也就是默认为ASCII 码[0,128) 内的字符,默认128个,这里题目指的是数字、字母、空格。


public int lengthOfLongestSubstring(String s) {
    //哈希
    Set<Character> sets = new HashSet<>();
    //右边指针
    int right = -1;
    int maxLen = 0;
    //优化点:进行剪枝
    for (int i = 0; i < s.length() - maxLen; i++) {
        //滑动窗口右移,移除左边一个元素
        if (i != 0) {
            sets.remove(s.charAt(i - 1));
        }
        //若是在指定范围内&添加成功
        while (right + 1 < s.length() && sets.add(s.charAt(right + 1))){
            right++;
        }
        maxLen = Math.max(right - i + 1, maxLen);
    }
    return maxLen;
}



2、滑动窗口(数组)


思路:题目给定范围那么ASCII码的数字表示即为[0-128]之间,1表示在滑动窗口中的了,0表示还未添加。


代码:时间复杂度O(n),空间复杂度O(∣Σ∣)


public int lengthOfLongestSubstring(String s) {
    //哈希
    int[] chars = new int[128];
    //右边指针
    int right = -1;
    int maxLen = 0;
    //优化点:进行剪枝
    for (int i = 0; i < s.length() - maxLen; i++) {
        //滑动窗口右移,移除左边一个元素
        if (i != 0) {
            chars[s.charAt(i - 1)] = 0;
        }
        //若是在指定范围内&添加成功
        while (right + 1 < s.length() && chars[s.charAt(right + 1)] == 0){
            chars[s.charAt(right + 1)] = 1;
            right++;
        }
        maxLen = Math.max(right - i + 1, maxLen);
    }
    return maxLen;
}




滑动窗口的最大值【困难】


题目链接:滑动窗口的最大值


题目内容:给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。


思路1:双端队列来进行。【推荐】


时间复杂度:O(n),数组长度为n,只遍历一遍数组。
空间复杂度:O(m),窗口长度m,双向队列最长时,将窗口填满。
class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        if (nums.length < k || nums.length == 0) {
            return new int[0];
        }
        int[] res = new int[nums.length - k + 1];
        int j = 0;
        //采用双端队列来解决
        ArrayDeque<Integer> deque = new ArrayDeque<>();
        //1、第一个窗口
        for (int i = 0; i < k; i++) {
            while (!deque.isEmpty() && nums[i] > deque.peekLast()) {
                deque.pollLast();
            }
            deque.addLast(nums[i]);
        }
        res[j++] = deque.peekFirst();
        //2、之后的窗口
        for (int i = k; i < nums.length; i++) {
            if (!deque.isEmpty() && deque.peekFirst() == nums[i - k]) {
                deque.pollFirst();
            }
            while (!deque.isEmpty() && nums[i] > deque.peekLast()) {
                deque.pollLast();
            }
            deque.addLast(nums[i]);
            res[j++] = deque.peekFirst();
        }
        return res;
    }
}
相关文章
|
29天前
|
算法
【算法】滑动窗口——最大连续1的个数
【算法】滑动窗口——最大连续1的个数
|
29天前
|
算法
【算法】滑动窗口——将x减到0的最小操作数
【算法】滑动窗口——将x减到0的最小操作数
|
29天前
|
算法 容器
【算法】滑动窗口——串联所有单词的子串
【算法】滑动窗口——串联所有单词的子串
|
29天前
|
算法
【算法】滑动窗口——最小覆盖子串
【算法】滑动窗口——最小覆盖子串
|
29天前
|
算法
【算法】滑动窗口——找到字符串中所有字母异位词
【算法】滑动窗口——找到字符串中所有字母异位词
|
29天前
|
算法
【算法】滑动窗口——无重复字符的最长子串
【算法】滑动窗口——无重复字符的最长子串
|
29天前
|
算法
【算法】滑动窗口——长度最小的子数组
【算法】滑动窗口——长度最小的子数组
|
29天前
|
算法
【算法】滑动窗口——水果成篮
【算法】滑动窗口——水果成篮
|
29天前
【刷题记录】最大公因数,最小公倍数(辗转相除法、欧几里得算法)
【刷题记录】最大公因数,最小公倍数(辗转相除法、欧几里得算法)
|
1月前
|
算法 Python
【Leetcode刷题Python】改进的算法,高效求一个数的因子
一个高效的Python函数用于找出一个整数的所有因子,通过仅遍历到该数平方根的范围来优化性能。
28 0