题目描述
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
输入: s = “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
输入: s = “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串
输入: s = “”
输出: 0
一、解题思路
解决在输入字符串、符号和数字等数据中寻找最长字串的问题,都可以使用滑动窗口这种算法。相比于使用双重循环,即以输入数据中每个元素作为起始点,再基于每个起始点来进行解题判断的时间复杂度为
O
(
N
2
)
O(N^2)
O(N2)的算法,滑动窗口可以将时间复杂度降为O(N)。
传统解题方法的思路如下所示,以abcabcbb为例子:
最终输出最长字串的长度为3。但是,这种解题方法的弊端在于,每次更新起左指针之后,右指针可能会重复判断(右指针初始化为左指针+1)。例如:第二次遍历对元素c进行了重复的判断,所以在完成所有遍历后,这种重复判断的情况更加明显。
引入滑动窗口算法可以解决上述问题。初始化左右指针,左指针代表字符串的起始位置,右指针代表出现的重复元素(在上一次遍历中与左指针指向相同元素)的下标,每一步操作将左指针右移一格,然后开始移动右指针,保证两个指针对应的字符串没有重复的字符。滑动窗口与传统方法不同的是,其右指针不会初始化,遍历完一次元素后就停止。
伪代码:
初始化 Hashset//其中没有重复元素
for 左指针 in 数组下标:
if 左指针!=0:
从Hashset中移除第一个元素
while 右指针<数据右边界&&Hashset中不包含右指针元素
向Hashset中加入右指针指向的元素
右指针++
result=Max(result,右指针-左指针)
二、JAVA代码
class Solution {
public int lengthOfLongestSubstring(String s) {
Set<Character> occur=new HashSet<Character>();
int flag=0,result=0;
for(int i=0;i<s.length();i++)
{
if(i!=0)
{
occur.remove(s.charAt(i-1));
}
while(flag<s.length()&&!occur.contains(s.charAt(flag)))
{
occur.add(s.charAt(flag));
flag++;
}
result=Math.max(result,flag-i);
}
return result;
}
}