leetcode-3-无重复字符的最长子串

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

class Solution{
    /*
    暴力法是遍历每一个字符串,检查是不是含有子串
    如果我们从索引i到i-1之间的子字符串已经被检查为没有重复字符,我们只需要检查对应的字符是否已经存在字符串中
    要检查一个字符串是否已经存在子字符串中,我们可以检查整个子字符串,这将产生了一个复杂度为O(n2)的算法
    通过使用hashset作为滑动窗口,我们可以用O(1)的时间来完成对字符串是否在当前的子字符串中的检查
    滑动窗口是数组/字符串问题中的常见的抽象,窗口通常是在数组/字符串中由开始和结束索引定义的一系列元素的集合
    即[i,j),而滑动窗口是可以将两个边界向某一方向滑动的窗口,
    我们使用hashset将字符串储存在当前窗口[i,j)中,然后我们向右滑动索引j,如果它不在hashset中
    我们将继续滑动j,直到s[j]已经存在于hashset中,此时,我们找到的没有重复字符的最长子字符串会将索引
    i开头,如果我们对所有的i都这样做,就可以找到答案
    */
    public int lengthOfLongestSubstring(String s) {
        int n = s.length();
        // 建立hashset
        Set<Character> set = new HashSet<>();
        // 定义最大值
        int ans = 0;
        // 定义窗口值的左右
        int i = 0, j = 0;
        //当窗口的左右都小于数组的长度的时候
        while (i < n && j < n) {
            // 判断hashset中是不是存在s.charAt(j)
            // 如果不存在加到滑动窗口里
            if (!set.contains(s.charAt(j))){
                set.add(s.charAt(j++));
                // 获取最大值
                ans = Math.max(ans, j - i);
            }
            else {
                //前面找到当前滑动窗口里面无重复子串的最大值,现在将滑动窗口往后滑动一个位置
                set.remove(s.charAt(i++));
            }
        }
        return ans;
    }
}

 

posted @ 2020-03-05 18:38  梁小松松松松松  阅读(100)  评论(0)    收藏  举报