LeetCode 3. Longest Substring Without Repeating Characters(最长无重复字符子串)

Given a string, find the length of the longest substring without repeating characters.

Examples:
Given "abcabcbb", the answer is "abc", which the length is 3.
Given "bbbbb", the answer is "b", with the length of 1.
Given "pwwkew", the answer is "wke", with the length of 3. Note that the answer must be a substring, "pwke" is a subsequence and not a substring.

大致意思就是给定一个字符串s,返回s的最长无重复字符子串的长度。
解决该题目最高效的方法是使用HashMap保存字符最近一次出现的位置。遍历每个字符时添加它到一个已有的无重复字符子串结尾,如果这个字符之前出现过,用HashMap查询它出现的位置,如果它已经在这个无重复字符子串中,更新子串的起点使这个字符加到子串末尾后仍保持无重复字符。通过这种方式,遍历一次字符串,就可以得到所有的无重复字符子串,统计它们的长度选出最大的即可。
如果n为字符串的长度,m为字符的编码范围。
下面代码的时间复杂度为O(n),空间复杂度为O(min(m, n)).

public class Solution {
    public int lengthOfLongestSubstring(String s) {

        Map latestIndex = new HashMap<>();  // 存放字符最近一次出现的位置
        int curStart = 0, curLen = 0, maxLen = 0;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);  // 添加字符c到一个已有的无重复字符子串结尾
            if (latestIndex.containsKey(c) && latestIndex.get(c) >= curStart) { // 字符c已经在这个无重复字符子串中
                curStart = latestIndex.get(c) + 1;  // 更新当前无重复字符子串的起点
            }
            curLen = i - curStart + 1;  // 当前无重复字符子串的长度
            if (curLen > maxLen) {
                maxLen = curLen;
            }
            latestIndex.put(c, i);
        }
        return maxLen;
    }
}

如果已知字符编码范围很小,我们可以使用整型数组代替上面的HashMap
整型数组大小对应的字符编码范围如下

  • int[26] for Letters 'a' - 'z' or 'A' - 'Z'
  • int[128] for ASCII
  • int[256] for Extended ASCII

下面代码的时间复杂度为O(n),空间复杂度为O(m).

public class Solution {
    public int lengthOfLongestSubstring(String s) {

        int[] latestIndex = new int[256];   // 存放字符最近一次出现的位置
        for (int i = 0; i < 256; i++) {
            latestIndex[i] = -1;
        }
        int curStart = 0, curLen = 0, maxLen = 0;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);   // 添加字符c到一个已有的无重复字符子串结尾
            if (latestIndex[c] >= curStart) {   // 字符c已经在这个无重复字符子串中
                curStart = latestIndex[c] + 1;  // 更新当前无重复字符子串的起点
            }
            curLen = i - curStart + 1;          // 当前无重复字符子串的长度
            if (curLen > maxLen) {
                maxLen = curLen;
            }
            latestIndex[c] = i;
        }
        return maxLen;
    }
}

你可能感兴趣的:(LeetCode 3. Longest Substring Without Repeating Characters(最长无重复字符子串))