算法题之求最大不重复子串的个数(滑动窗口)
题目描述
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: “pwwkpw”
输出: 3
解释: 因为无重复字符的最长子串是 “kpw”,所以其长度为 3。
题解(滑动窗口)
以输入: "pwwkpw"为例

滑动窗口思路分析:利用HashMap的键唯一性
- (1)当我们判断字符串当前字符在HashMap中key中未曾出现过:
- 则直接将其加入到HashMap中:其中键(key)即为当前的字符(Character),值(value)即为该字符在String字符串的索引
- 其中此时的最大字符串的最大长度(maxLength)即为当前索引 – left(初始值为0) + 1;第一次添加p,则maxLength = 1;
- (2)若依次添加字符,字符key值未在HashMap中出现过,则一直将其加入HashMap中,故p,w的maxLength = 1 – left + 1 = 2;
- (3)若添加字符,当前key值在HashMap中出现过,根据HashMap的键唯一性:
- 首先我们需要更新此时的left指针变量,即更新窗口的滑动:
- 开始时,left位于0位置,此时,选择之前的left指针和当前key值字符的位置 + 1,即移除重复出现的字符,取两者的最大值为新的left指针
- 故此时的left为2,此时再将当前键值加入HashMap集合中时,替换之前的value值,即更新w的索引位置,而此时的maxLength,即为之前的maxLength[p,w = 2]和现在的i – left + 1 = 1[w]的最大值
- 接着,也是同上思路,当遍历到p字符时,需要更新left的位置:因为先前的left索引大于此时p之前的索引 + 1,则窗口不发生偏移
maxLength = [p,w] vs [w,k,p] = 3; - 最后到w,更新left位置为k的位置,此时maxLength = [w,k,p] vs [k,p,w] = 3;
- (4)故最终的maxLength = 3;即最大的非重复子串的长度为:3.
图解过程


代码实现
public static void main(String[] args) {
String str = "pwwkpw";
LongestSubString2 solution = new LongestSubString2();
int maxLength = solution.lengthOfLongestSubstring(str);
System.out.println("最大不重复的子字符串的长度为: " + maxLength);
}
private int lengthOfLongestSubstring(String s) {
//定义该字符串的长度为n
int n = s.length();
//若长度小于等于1,则maxLength即为字符串本身的长度,直接返回
if (n <= 1) {
return n;
}
//定义maxLength作为最大不重复子串的长度
int maxLength = 0;
//定义滑动窗口的左指针的变量,初始化为0
int left = 0;
//定义一个HashMap进行存储
HashMap<Character,Integer> hashMap = new HashMap<>();
for (int i = 0; i < n; i++) {
if (hashMap.containsKey(s.charAt(i))) {
//如果当前key值在hashmap中已经存在
//则更新left指针为之前的出现的指针向右平移一位
left = Math.max(left, hashMap.get(s.charAt(i)) + 1);
}
//将该键值添加到hashmap集合中
hashMap.put(s.charAt(i),i);
maxLength = Math.max(maxLength,i - left + 1);
}
//返回最大值maxLength
return maxLength;
}

本文介绍了一种使用滑动窗口方法解决寻找字符串中最长无重复字符子串的问题,并通过示例详细解析了算法流程。
1656

被折叠的 条评论
为什么被折叠?



