3 .最长的子串不重复字符

给定一个字符串,找到最长的子字符串的长度,不重复字符。

例子:

给定”abcabcbb”的答案是”abc”,长度是3。

给定”bbbbb”的答案是”b”,长度为1。

给定”pwwkew”的答案是”wke”,长度为3.请注意,答案必须是一个子字符串,”pwke”是一个子序列,而不是一个子字符串。

2滑动窗口[接受]
算法

天真的做法是非常简单的。但是太慢了。那么我们如何优化呢?

在天真的方法中,我们重复检查一个子字符串,看它是否有重复的字符。但是这是没有必要的。如果一个子串s​ij
​从索引一世i去j – 1已经检查了 j – 1没有重复的字符。我们只需要检查一下S [j]的s [ j ]已经在子字符串中了s​ij

要检查一个字符是否已经在子字符串中,我们可以扫描子字符串,这会导致一个 为O(n ^ 2)ø (Ñ
2
)算法。但是我们可以做得更好。

通过使用HashSet作为滑动窗口,检查当前的字符是否可以在其中完成 O(1)O (1 )。

滑动窗口是数组/字符串问题中常用的抽象概念。窗口是数组/字符串中通常由开始和结束索引定义的一系列元素,即[i,j)[ i ,j )(左转,右转)。滑动窗口是将其两个边界“滑”到某个方向的窗口。例如,如果我们滑动[i,j)[ i ,j )在右边11元素,然后它成为[i + 1,j + 1)[ i + 1 ,j + 1 )(左闭,右开)。

回到我们的问题。我们使用HashSet来存储当前窗口中的字符[i,j)[ i ,j )(j = ij = 我最初)。然后我们滑动索引Ĵj在右边。如果它不在HashSet中,我们滑动Ĵj进一步。这样做直到s [j]已经在HashSet中。此时,我们发现没有重复字符的子字符串的最大尺寸以索引开始一世我。如果我们这样做的话一世我,我们得到我们的答案。

class Solution {
    public int lengthOfLongestSubstring(String s) {
        Set<Character> set = new HashSet<Character>();
        int start =0,end =0,result =0;
        int n = s.length();
        while (start<n&&end<n){ if(!set.contains(s.charAt(end))){ set.add(s.charAt(end++));
                result = Math.max(result,end-start);
            }
            else{
                set.remove(s.charAt(start++));
            }
        }
        return result;
    }
}
点赞