算法通关村第十六关—滑动窗口经典问题(白银)

  滑动窗口经典问题

一、最长子串专题

1.1 无重复字符的最长子串

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

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

 要找最长子串,必然要知道无重复字符串的首和尾,然后再从中确定最长的那个,因此至少两个指针才可以,这就想到了滑动窗口思想。
 定义一个K-V形式的map,key表示的是当前正在访问的字符串,value,是其下标索引值。我们每访问一个新元素,都将其下标更新成对应的索引值。具体过程如下图:
image.png
 如果是已经出现过的,例如上述示例中的abcabc,当第二次遇到a时,我们就更新left成为第一个b所在的位置,此时发现left要移动的位置恰好就是map.get(‘a’)+1=1,将’a’用序列来表示,放在一起就是map.get(s.charAt(i)+1。其他情况可以参考图示依次类推。
 有一种特殊情况是需要考虑的,例如abba,我们第二次访问b时, left=map.get('b)+1=2。然后继续访问第二个a,此时left=map.get('a‘)+1=1,也就是left后退了,显然不对。
 我们应该让t在2的基础上继续向前,那该怎么办呢?和原来的对比一下,将最大的加1就可以了,也就是:left=Math.max(left,map.get(s.charAt(i))+1);
完整的代码如下:

class Solution {public int lengthOfLongestSubstring(String s) {int n = s.length(),max = 0; Map<Character, Integer> map = new HashMap<>(); for(int end = 0, start = 0; end < n; end++){ char element = s.charAt(end); if(map.containsKey(element)){ start = Math.max(map.get(element)+1, start);}max = Math.max(max, end - start + 1);  map.put(element, end);  }return max;}
}

1.2 至多包含两个不同字符的最长子串

 LeetCode159题 给定一个字符串S,找出至多包含两个不同字符的最长子串t,并返回该子串的长度。例如:

输入:"eceba"
输出:3
解释:t是"ece",长度为3

 我们仍然使用Ieft和ight来锁定一个窗口,然后一边向右移动一边分析。我们用一个序列来看一下:aabbcccd。
image.png
 我们接下来需要解决两个问题,一个是怎么判断只有2个元素,另一个是移除的时候怎么知道移除谁,以及移除之后left是什么。
 要判断只有2个元素,还是Hash好用,每一个时刻,这个hashmap包括不超过3个元素。这里还要考虑到要移除谁,所以我们要设计一下Hash的Key-Valuet的含义。我们把字符串里的字符都当做键,在窗口中的最右边的字符位置作为值。此时使用下面的代码就可以确定要删除谁,以及窗口left的新位置:

//伪码,从Hash中找最小值
del_idx = Collections.min(hashmap.values());
left = del_idx + 1;

image.png

public int lengthofLongestSubstringTwoDistinct(String s){
if(s.length() < 3){return s.length();
}
int left = 0, right = 0;
HashMap<Character,Integer> hashmap = new HashMap();
int maxLen = 2;
while(right < s.length()){if(hashmap.size() < 3)hashmap.put(s.charAt(right),right++);//如果大小达到了3个if(hashmap.size()==3){//最左侧要删除的位置int del_idx = Collections.min(hashmap.values());hashmap.remove(s.charAt(delidx));//窗口left的新位置left = del_idx + 1;}maxLen = Math.max(maxLen, right -left);
}
return maxLen;
}

1.3 至多包含K个不同字符的最长子串

 如果再提高一下难度,至多包含K个不同字符的最长子串该怎么办呢?这是LeetCode340题。题目的完整要求是:给定一个字符串S,找出至多包含k个不同字符的最长子串T。示例:

输入:S="eceba",k=2
输出:3
解释:则T"ece",所以长度为3

 本题与上面的题几乎没有区别,只要将判断hash大小为2改成k就可以,超过2就是k+1。十分钟实现:

public int lengthofLongestSubstringTwoDistinct(String s, int k){
if(s.length() < k + 1){return s.length();
}
int left = 0, right = 0;
HashMap<Character,Integer> hashmap = new HashMap();
int maxLen = k;
while(right < s.length()){if(hashmap.size() < k + 1)hashmap.put(s.charAt(right),right++);//如果大小达到了k+1个if(hashmap.size()== k + 1){//最左侧要删除的位置int del_idx = Collections.min(hashmap.values());hashmap.remove(s.charAt(delidx));//窗口left的新位置left = del_idx + 1;}maxLen = Math.max(maxLen, right -left);
}
return maxLen;
}

二、长度最小的子数组

 LeetCode209.长度最小的子数组,给定一个含有n个正整数的数组和一个正整数target。找出该数组中满足其和≥target的长度最小的连续子数组[numsl,numsl±1,numsr-1,numsr],并返回其长度。如果不存在符合条件的子数组,返回0。

输入:target=7,nums=[2,3,1,2,4,3]
输出:2
解释:子数组[4,3]是该条件下的长度最小的子数组。

 本题可以使用双指针来解决,也可以视为队列法,基本思路是先让元素不断入队,当入队元素和等于target时就记录一下此时队列的容量,如果队列元素之和大于target则开始出队,直到小于target则再入队。
 如果出现等于target的情况,则记录一下此时队列的大小,之后继续先入队再出队。每当出现元素之和等于target时我们就保留容量最小的那个。

class Solution {public int minSubArrayLen(int target, int[] nums) {int left = 0, right = 0;int sum = 0;int min = nums.length + 1;for(right = 0; right < nums.length; right++){sum+= nums[right];if(sum >= target){for(;left < right; left++){if(sum - nums[left]>= target) sum -= nums[left];else break;}min = Math.min(min, right - left + 1);}}return min == nums.length + 1? 0 : min;}
}

三.盛水最多的容器

 LeetCode11.给定一个长度为n的整数数组height。有n条垂线,第i条线的两个端点是(i,0)和(i,height[i])。找出其中的两条线,使得它们与×轴共同构成的容器可以容纳最多的水。返回容器可以储存的最大水量。
image.png
平平无奇双指针,下面自己的解法

class Solution {public int maxArea(int[] height) {int left = 0,right = height.length-1; //创建左右指针,分别指向数组的开端和末端int max = 0; //max用于记录最大值while(left < right){ //当左右指针还未重合时int v = (right - left) * Math.min(height[left] , height[right]); //计算当前的容水量max = max > v ? max : v; //利用三目运算符判断最大值是否需要改变if(height[left] < height[right]) left++;  //对指向 高度比较低 的指针进行移动else right--;}return max; //返回最大值}
}

讲义解法,压缩版

public int maxArea(int[] height){int i=0,j=height.length -1,res 0;while(i<j){res = height[i] < height[j] ?Math.max(res,(j-i)*height[i++]):Math.max(res,(j-i)height [j--]);}return res;
}

四、寻找子串异位词(排列)

4.1 字符串的排列

 LeetCode567.给你两个字符串s1和s2,写一个函数来判断s2是否包含s1的排列。如果是,返回true;否则,返回flse。换句话说,s1的排列之一是s2的子串。其中s1和s2都只包含小写字母。

示例:
输入:s1="ab"s2="eidba00o"
输出:true
解释:s2包含s1的排列之一("ba").
public boolean checkInclusion(String s1, String s2) {if(s1.length() > s2.length()) return false;int[] arr1 = new int[26];int[] arr2 = new int[26];for(int i = 0; i < s1.length(); i++){arr1[s1.charAt(i) - 'a']++;arr2[s2.charAt(i) - 'a']++;}if(Arrays.equals(arr1,arr2)) return true;int j = 0;for(int i = s1.length(); i < s2.length(); i++){arr2[s2.charAt(i) - 'a']++;arr2[s2.charAt(j) - 'a']--;j++;if(Arrays.equals(arr1,arr2)) return true;}return false;}
}

4.2 找到字符串中所有字母异位

 LeetCode438.找到字符串中所有字母异位词,给定两个字符串s和p,找到s中所有p的异位词的子串,返回这些子串的起始索引。不考虑答案输出的顺序。注意s和ρ仅包含小写字母。异位词指由相同字母重排列形成的字符串(包括相同的字符串)。
例如:

输入:s="cbaebabacd",p="abc"
输出:[0,6]
解释:
起始索引等于0的子串是
"cba",它是"abc"的异位词。
起始索引等于6的子串是"bac",它是"abc"的异位词。

 本题的思路和实现与上面几乎一模一样,唯一不同的是需要用一个List,如果出现异位词,还要记录其开始位置,那直接将其add到List中就可以了。完整代码:

class Solution {public List<Integer> findAnagrams(String s, String p) {List<Integer> list = new ArrayList();if(s.length() < p.length()) return list;int[] arr1 = new int[26]; //保存pint[] arr2 = new int[26]; //保存sfor(int i = 0; i < p.length(); i++){arr1[p.charAt(i) - 'a']++;arr2[s.charAt(i) - 'a']++;}if(Arrays.equals(arr1,arr2)) list.add(0);int left = 0;for(int right = p.length(); right < s.length(); right++){arr2[s.charAt(right) - 'a']++;arr2[s.charAt(left) - 'a']--;left++;if(Arrays.equals(arr1,arr2)) list.add(left);}return list;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/625645.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Java万花筒】数据之舞:Java数据库连接与操作库全景视角

数据库连接与操作&#xff1a;Java 应用开发者的综合指南 前言 随着Java应用的不断发展&#xff0c;数据库连接与操作成为关键技能之一。本文将深入探讨主流Java库&#xff0c;涵盖了JDBC、Hibernate、MyBatis、Spring Data JPA、Apache Commons DBUtils、JOOQ以及Querydsl。…

牛客周赛 Round 28 F

以后需要使用map&#xff0c;set进行二分&#xff0c;并且需要知道二分位置的信息时&#xff0c;不妨考虑使用树状数组进行维护 因为简单版本保证了每个数都为正整数&#xff0c;所以前缀和保证了一定的递增的&#xff0c;即有序的&#xff0c;那么考虑固定左端点&#xff0c;去…

多线程并发与并行

&#x1f4d1;前言 本文主要是【并发与并行】——并发与并行的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#x1f304;每日一句&…

自动化测试理论(1)—概述需要掌握的内容

要在自动化测试领域取得成功&#xff0c;需要掌握一系列技能和概念。以下是一些关键的内容&#xff1a; 编程语言&#xff1a; 了解并精通至少一种编程语言&#xff0c;如Python&#xff0c;Java&#xff0c;JavaScript等。编写自动化测试脚本通常需要编程技能。 自动化测试框…

SpringBoot3

有用的新特性 JDK8-19 新增了不少新特性&#xff0c;这里我们把实际常用的新特性&#xff0c;给大家介绍一下。包括以下几个方面&#xff1a; Java RecordSwich 开关表达式Text Block 文本块var 声明局部变量sealed 密封类 Java14 中预览的新特性叫做 Record &#xff0c;在…

explorer.exe 作用

Explorer.exe是什么 在Windows操作系统中&#xff0c;Explorer.exe是桌面进程的意思&#xff0c;它负责显示用户桌面信息&#xff0c;如果用户将它结束掉就看不到桌面上的任何图标了&#xff0c;相当于Windows操作系统中的人机交互界面&#xff0c;其重要性不言而喻。如果用户发…

【算法笔记】分支限界专题

分支限界 整体结构 本质上感觉还是遍历解树剪枝&#xff0c;但是配合优先队列使用以后可以更好的找到最优解。 例题 P8011 ⾛迷宫 对于迷宫问题&#xff0c;某一节点的关联节点指的是它四个方向上相邻的节点。 要利用flag数组确保不会重复访问。 void bfs(){//1、初始化队…

重写equals方法为什么还要重写hashcode方法?

目录 什么是 hashcode&#xff08;哈希码、散列码&#xff09;&#xff1f; 为什么 equals() 方法要重写&#xff1f; hashCode() 与 equals() 的关系 重写equals方法为什么还要重写hashcode方法&#xff1f; 什么是 hashcode&#xff08;哈希码、散列码&#xff09;&#…

python爬虫之线程与多进程知识点记录

一、线程 1、概念 线程 在一个进程的内部&#xff0c;要同时干多件事&#xff0c;就需要同时运行多个“子任务”&#xff0c;我们把进程内的这些“子任务”叫做线程 是操作系统能够进行运算调度的最小单位。它被包含在进程之中&#xff0c;是进程中的实际运作单位。一条线程指…

DAY01_Spring—Spring框架介绍IOCSpring工厂模式

目录 1 什么是框架2 Spring框架2.1 Spring介绍2.2 MVC模型说明2.3 IOC思想2.3.1 问题说明2.3.2 IOC说明 3 Spring IOC具体实现3.1 环境准备3.1.1 关于JDK说明3.1.2 检查JDK环境配置 3.2 创建项目3.3 关于Maven 命令3.3.1 install 命令3.3.2 clean 命令 3.4 添加jar包文件3.4.1 …

flutter使用getx进行数据状态管理,实现页面响应式

无论是什么样的应用&#xff0c;都还是需要最基础的数据来支撑的&#xff0c;而且不同的页面之间可能需要共享数据状态&#xff0c;这就显得数据状态管理非常有必要了。因为我这里使用了get依赖库&#xff0c;所以就可以直接在项目中使用getx来管理状态&#xff0c;不想再使用别…

【笔记】软件下载链接汇总

&#x1f388;欢迎加群交流&#x1f388; ✨✨✨https://ling71.cn/hmf.jpg✨✨✨ 浏览器历史版本下载 Firefox史版本下载&#xff1a;&#xff08;官网&#xff09; http://ftp.mozilla.org/pub/mozilla.org//firefox/releases/ Chrome历史版本、ChromeDriver历史版本&#x…

服务器机房上架交付流程

服务器上架交付 服务器到货验收后&#xff0c;会进行机房机房上架&#xff0c;完成重装系统、网络配置后交付使用 1、到货验收 采购服务器到货后&#xff0c;会联合多部门进行SN、配置、数量等多方面验收&#xff0c;如数量是否匹配&#xff0c;配置是否相符等也会拆开机箱看看…

Python基础知识:整理10 异常相关知识

1 异常的捕获 1.1 基础写法 """基本语法&#xff1a;try:可能发生错误的代码except:如果出现异常&#xff0c;将执行的代码""" try:fr open("D:/abc.txt", "r", encoding"utf-8") except:print("出现异常…

APM传感器校准

文章目录 前言一、校准加速度计二、校准罗盘三、校准陀螺仪四、校平地平线 前言 固件&#xff1a;rover 4.2.3 地面站&#xff1a;独家汉化版QGC 一、校准加速度计 点击左上角软件图标-》载具设置-》传感器-》加速度计 飞控方向默认为None即可&#xff0c;点击确定 点击确…

德语怎么翻译,中文翻译成德文有何要求?

近年来&#xff0c;随着中德之间的贸易往来日益频繁&#xff0c;德语翻译需求在市场上持续升温。那么&#xff0c;如何做好德语翻译&#xff0c;特别是将中文翻译成德文需要注意哪些要求呢&#xff1f; 首先&#xff0c;深入理解中文原文的语境和含义至关重要。中文含蓄且抽象&…

存储的基本架构

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、存储的需求背景二、自下而上存储架构总结 一、存储的需求背景 1、人的身份信息需要存储 这种信息可以用关系型数据库&#xff0c;例如mysql&#xff0c;那种表…

c++的宏举例和理解

宏提供了一种机制&#xff0c;能够使你在编译期替换代码中的符号或者语句。当你的代码中存在大量相似的、重复的代码时&#xff0c;使用宏可以极大的减少代码量&#xff0c;便于书写。 // 定义圆周率 #define PI 3.14159265 // 定义一个空指针 #define NULL ((void*)0) // 定…

第十二章 Java内存模型与线程(二)

文章目录 12.4 Java与线程12.4.1 线程的实现12.4.2 Java线程调度12.4.3 状态转换 12.4 Java与线程 12.4.1 线程的实现 实现线程主要有三种方式&#xff1a;使用内核线程实现&#xff08;1&#xff1a; 1 实现&#xff09;&#xff0c;使用用户线程实现&#xff08;1&#xff…

CMake入门教程【高级篇】自定义的构建命令add_custom_command

文章目录 1.概述信息2.命令作用3.完整代码示例4. 实际使用中的技巧1.概述信息 add_custom_command是一个非常强大的工具,它允许用户定义在构建过程中执行的自定义命令。这可以用于生成源文件、执行前后处理步骤、自动化测试等。 #mermaid-svg-9icMsOnoxbNTRCu0 {font-family:…