滑动窗口系列(不定长滑动窗口长度) 9/1

1.无重复字符的最长子串

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

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

不定长的滑动窗口长度,其中windowSize=无重复字符的最长字串的长度;

那么如何得到最长字串的长度?

使用哈希表+while循环遍历

如果遍历到的字母在哈希表中存在,此时字串中出现重复字符;

此时我们就要移动left改变滑动窗口的左边界;使得哈希表中不再出现s.charAt(right);

因为新的字符串的开始一定是不包含重复字符的,如果左边界还是出现了s.charAt(right),那么它的长度一定比之前的小;

复制代码
 while (map.getOrDefault(ch, 0) != 0) {
                max = Math.max(max, right - left);
                map.put(s.charAt(left),map.get(s.charAt(left))-1);
                left++;
            }
代码:
复制代码
class Solution {
    public int lengthOfLongestSubstring(String s) {
        Map<Character, Integer> map = new HashMap<>();
        int max = 0;
        int left = 0;
        int right = 0;
        while (right < s.length()) {
            char ch = s.charAt(right);
            while (map.getOrDefault(ch, 0) != 0) {
                max = Math.max(max, right - left);
                map.put(s.charAt(left),map.get(s.charAt(left))-1);
                left++;
            }
            map.put(ch, map.getOrDefault(ch, 0) + 1);
            right++;
        }
        max=Math.max(max,right-left);
        return max;
    }
}

2.找到最长的半重复子字符串

给你一个下标从 0 开始的字符串 s ,这个字符串只包含 09 的数字字符。

如果一个字符串 t 中至多有一对相邻字符是相等的,那么称这个字符串 t半重复的

**输入:**s = "52233"

**输出:**4

解释:

最长的半重复子字符串是 "5223"。整个字符串 "52233" 有两个相邻的相同数字对 22 和 33,但最多只能选取一个。

思路:

滑动窗口大小未知,当相邻的相同数字存在两对的时候,此时滑动窗口就要左移;

那么左移到什么地方就可以停止了?左移到相邻的相同数字只存在一对的时候;

复制代码
            while(count>1){
                if(s.charAt(left)==s.charAt(left+1))count--;
                left++;
            }
代码:
复制代码
class Solution {
    public int longestSemiRepetitiveSubstring(String s) {
        int count=0;
        int max=0;
        int left=0;
        int right=0;
        while(right<s.length()){
            if(right>0&&s.charAt(right)==s.charAt(right-1)){
                count++;
            }
            while(count>1){
                if(s.charAt(left)==s.charAt(left+1))count--;
                left++;
            }
            max=Math.max(max,right-left+1);
            right++;
        }
        return max;
    }
}

模板:

题目中会给出限制滑动窗口的长度的条件,然后循环遍历每一个元素,首先判断是否会对条件有影响;当不满足题目中的条件之后,就要移动滑动窗口的左边界,直至满足;

eg:第一题中是子串中不含有无重复字符;

eg:第二题中是子串中半重复字符对只可以出现一次

复制代码
class Solution {
    public int longestSemiRepetitiveSubstring(String s) {
        int res=0;
        int left=0;
        int right=0;
        while(right<s.length()){
            if(题目中需要满足的条件){
                count++;
            }
            //如果条件不满足,就要移动左边界直至条件满足
            while(不满足的条件){
              //移动左边界
            }
            max=Math.max(max,right-left+1);
            right++;
        }
        return max;
    }
}

3.数组的最大美丽值(排序+滑动窗口)

题意:

给定一个数组nums,k。数组中的每一个值都可以替换成(numsi-k,numsi+k)中的任意一个数。

数组的美丽值:数组中元素相同的个数有多少个;

求数组的最大美丽值

复制代码
输入:nums = [4,6,1,2], k = 2
输出:3  

4 4 1 4

思路:

这道题其实考的就是最大重叠区间,数组中每一个数组都对应了一个区间,求最大重叠区间的个数是多少。

排好序之后,判断numsright和numsleft之间的差值和2*k的关系

为什么是2*k呢?因为numsright可以被替换成-k以内的,而numsleft可以被替换成+k以内的,所以只要相差在2k以内,就有公共区域

代码:
复制代码
class Solution {
    public int maximumBeauty(int[] nums, int k) {
        Arrays.sort(nums);
        int res=0;
        int left=0;
        int right=0;
        while(right<nums.length){
            if(nums[right]-nums[left]>2*k)left++;
            res=Math.max(res,right-left+1);
            right++;
        }
        return res;
    }
}

总结:定长滑动窗口/不定长滑动窗口的区别

定长滑动窗口:每次left右移 只需要移动一次,因为滑动窗口的长度是固定的;
不定长滑动窗口:每次left右移,需要移动到满足题目中的条件为止,因此窗口的长度是不固定的
相关推荐
CSharp精选营4 天前
关系型 vs 非关系型:从原理到选型,一文搞定数据库核心分类
数据结构·nosql·关系型数据库·非关系型数据库·技术选型
刘马想放假7 天前
Modbus 全栈技术解析:TCP、RTU、ASCII、RTU over TCP
数据结构·网络协议
北域码匠8 天前
冒泡排序太慢?鸡尾酒排序双向优化,原生 C# 零第三方库完整代码
数据结构·排序算法·泛型·c# 算法·鸡尾酒排序·原生 c# 开发·冒泡排序优化·嵌入式算法
Darling噜啦啦15 天前
列表转树算法深度解析:从 Map 到 Reduce 的两种实现,面试高频考点
数据结构·算法·面试
小小工匠16 天前
Redis - 事务机制:能实现 ACID 属性吗
数据结构·redis·性能优化·并发·持久化
玖玥拾16 天前
C/C++ 数据结构(七)栈、容器适配器
c语言·数据结构·c++··容器适配器
Qres82116 天前
算法复键——树状数组
数据结构·算法
牛油果子哥q16 天前
并查集(DSU)超精讲,路径压缩、按秩合并、万能模板、连通性判定、最小生成树与刷题实战全解
数据结构·c++·最小生成树·并查集
凌波粒16 天前
LeetCode--491.递增子序列(回溯算法)
数据结构·算法·leetcode
WL学习笔记16 天前
单项不带头不循环链表
数据结构·链表