详解Leecode-03:无重复最长子串

版权声明:本文为博主原创文章,转载联系 [email protected] https://blog.csdn.net/qq_31573519/article/details/82501033

1. 暴力穷举遍历(慢)

    /**
     * #3
     * 无重复最长字符子串
     * https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/description/
     * @param s
     * @return
     */
    /** 方法一:暴力遍历 **/
    public int lengthOfLongestSubstring (String s){
        // 获取原始字符串的长度
        int n = s.length();
        // 初始化为结果的长度为0
        int ans = 0;
        // 暴力遍历,定义2个游标,第一个游标从0位置开始,2个游标之间最短距离就是一个字符长度,那么j就应该从i+1开始
        for (int i = 0; i < n; i ++){
            for (int j = i + 1; j <= n; j ++){
                // 调用allUnique函数,allUnique函数会判断在每一次的字符子串遍历中,是否包含该单个字符
                if (allUnique(s, i, j)) { ans = Math.max(ans, j - i);}
            }
        }
        return ans;
    }
    public boolean allUnique(String s, int start, int end){
        // 定义一个Set集合,存储判断过的字符
        Set<Character> set = new HashSet<Character>();
        // 在开始和结束的下标之间,遍历下标获取字符串中的单个字符
        for (int i=start; i<end; i++){
            // 一边遍历,一边判断 set集合中是否已经包含当前获得的字符,如果判断到了包含,那么说明字符已经开始重复
            if (set.contains(s.charAt(i))){
                return false;
            }
            set.add(s.charAt(i));
        }
        // 最坏的情况下,在start和end的范围内,每个字符都不包含,那么直接return true
        return true;
    }

2. 滑动窗口

    /** 方法二:滑动窗口 **/
    public int lengthOfLongestSubstringSlidingWindow (String s){
        // 初始化定义返回结果,原始字符串长度,遍历游标
        int n = s.length(), ans = 0, i = 0, j = 0;
        // 定义存储单个字符的 HashSet(无序不重复)
        Set<Character> set  = new HashSet<Character>(n);
        // 在 i、j都在 n的范围内进行从左向后的遍历
        // 可以想象为有一个窗口,在一个字符串上进行从左向右的滑动
        // 初始状态下,这个窗口是一个[i,j),左闭,右开的范围
        // 然后 i、j 依次开始累加,要么左区间向右移动一格,要么右区间向右移动一格,依次向后
        // 所以最坏的情况下,每个元素都被i和j访问2次,复杂度为 O(2n) = O(n)
        while (i < n && j < n){
            // 判断窗口右端的值是否在Set中,如果不在,那么把元素塞到Set里,形象到窗口中就是右区间向右移动一格
            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;
    }

猜你喜欢

转载自blog.csdn.net/qq_31573519/article/details/82501033
今日推荐