LintCode 384. 最长无重复字符的子串

原题

第一步,万年不变的查错。如果给的string是null或长度为0,那么直接return。

    public int lengthOfLongestSubstring(String s) {
        if (s == null || s.length() == 0) {
            return 0;
        }
        ...
    }

大致思路就是,两个pointer,前向移动第二个pointer,每次移动更新最大长度,碰到重复的,就移动第一个pointer直到没有重复的,再继续移动第二个,直到整个string被遍历完。
那么第一步,就是建一个hashmap用来去重。

        Map hash = new HashMap<>();

然后就是遍历并打擂台。如果遇到重复的,把之前遇到过的去掉,直到没有重复的为止。如果当前character不是重复的,那就更新最大length,然后记录下来遍历过这个character。遍历完后,return最大长度。

        int j = 0;
        int maxLength = Integer.MIN_VALUE;
        for (int i = 0; i < s.length(); i++) {
            while (j < s.length() && !hash.getOrDefault(s.charAt(j), false)) {
                hash.put(s.charAt(j), true);
                maxLength = Math.max(maxLength, j - i + 1);
                j++;
            }
            hash.put(s.charAt(i), false);
        }
        return maxLength;

完整的code

public class Solution {
    /*
     * @param s: a string
     * @return: an integer
     */
    public int lengthOfLongestSubstring(String s) {
        if (s == null || s.length() == 0) {
            return 0;
        }

        Map hash = new HashMap<>();
        int j = 0;
        int maxLength = Integer.MIN_VALUE;
        for (int i = 0; i < s.length(); i++) {
            while (j < s.length() && !hash.getOrDefault(s.charAt(j), false)) {
                hash.put(s.charAt(j), true);
                maxLength = Math.max(maxLength, j - i + 1);
                j++;
            }
            hash.put(s.charAt(i), false);
        }

        return maxLength;
    }
}

分析

空间复杂度是O(n),n为s的长度。时间复杂度是O(2n),也就是O(n)。因为两个pointer遍历了string两遍。有些小的优化,比如知道s只有26个字母的话,那么不需要hashMap,可以直接用长度为26的boolean[]。如果是ASCII,那就长度为256的boolean[]。如果是unicode,还是老老实实用hashmap吧。

总的来说,这道题就是很简单的一道two pointer问题,唯一需要记住的一点就是不需要两个for loop,因为当i改变时,j不需要回到i的位置。

你可能感兴趣的:(LintCode 384. 最长无重复字符的子串)