LeetCode
题目来源
无重复字符的最长子串
- 题目描述
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
- 示例
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
- 题解一
以i作为子字符串的左指针,以right作为子字符串的右指针,右指针right不断右移,直到right所指向的下一个字符(即right+1)与左指针i指向的字符相同,此时,i到right之间(包括right)的子字符串是符合没有重复字符的子字符串,将该子字符串的长度与已记录符合条件的最长子字符串的长度相比较,若长于则更新,然后左指针左移,重复相同的操作,直至最后一个字符。
代码:
class Solution {
public int lengthOfLongestSubstring(String s) {
Set<Character> str = new HashSet(); //用于保存当前不含重复字符的子串
int right = -1;//子串的最后一个字符的下标
int res = 0;//最长子串的长度
for(int i = 0; i < s.length() - res; i++)
{
if( i != 0)//如果不是刚开始判断,将当前判断的字符串最左的一个字符去除
{
str.remove(s.charAt( i-1 ));
}
//如果右指针没有移动到最后,且当前子串中没有包含下一个字符
while(right + 1 < s.length() && !str.contains(s.charAt( right+1 )))
{
str.add(s.charAt( right+1 ));
right++;
}
res = Math.max(res, right-i+1);
}
return res;
}
}
- 题解二
通过begin标记开始查找重复字符的起始位置,以第i个字符作为查找对象,
当第i个字符在i与begin之间只出现一次时,indexOf的结果必等于i,
当在第i个字符之前出现与第i个字符相同的字符时,此时符合条件的子字符串的长度为i左移的次数,通过len 来记录字符串的长度
当indexOf的查找结果pos<i时,如果当前符合条件的字符串长度len>已记录的符合条件的最长子字符串的长度res,则更新res。此时,如果字符串从重复字符的下一个字符即pos+1开始到字符串结尾的长度小于res,则结束查找。否则,更新开始查找的位置begin为重复字符的下一个,更新从当前begin到i左移的次数到len。
因为可能会出现从开始到查找结束都不出现pos<i的情况,此时res=0,为刚初始化的值,并未更新,此时应返回len
class Solution {
public int lengthOfLongestSubstring(String s) {
int res = 0;//最长子串的长度
int i = 0; //查找第i个元素
int begin = 0; //子串第一个字母的下标
int len = 0;//用于记录查找时子字符串的长度
while( i < s.length() )
{
int pos = s.indexOf(s.charAt(i),begin);//查找第i个元素第一次重复时所在位置
//当子串中没有出现重复字母时,pos应等于i
//当子串中出现重复字母时,pos应该小于i
if(pos < i)
{
if( res < len )
{
res = len;
}
if( res >= s.length() - pos - 1)
{
return res;
}
len = i - pos - 1;
begin = pos + 1 ;
}
i++;
len++;//当前符合条件的子字符串长度
}
return len;
}
}