1

题目描述:

Given a string, find the length of the longest substring without repeating characters. For example, the longest substring without repeating letters for "abcabcbb" is "abc", which the length is 3. For "bbbbb" the longest substring is "b", with the length of 1.

分类:普通

1A:False

分析:

这种题暴搜肯定是会超时的。

所以应该安排两下标,一个记录起点start,一个记录当前下标head。当发现当前字符已经在串中存在的时候,重置起点。

问题就在于如何重置起点了,如果当前起点是0, 当前下标是9,那么最最原始的方法就是把下起点重置为1,但这样就退化成暴搜了。

假设字符串为“acbdefgh d mnty”,假设起点是0,当前下标是粗体d所在处,可以看出粗体的d和前面的d发生了重复,无论我们把起点重置为c,b还是d,子串都会毫无意外地和当前的粗体d产生重复字符,因此我们只需要把起点重置到e处即可。

但如何知道e在何处呢,我们可以采用HashMap来保存某个字符所处的下标即可,如map['d'] = 3,那么我们把起点重置到4即可。

代码:

public class Solution {
    public int lengthOfLongestSubstring(String s) {
        int[] chars = new int[26]; //把这个当HashMap用了
        int len = s.length();
        int code = 0;
        int max = 0;

        // 0和1的情况根本不用计算,直接返回更安全
        if (len == 0) return 0;
        if (len == 1) return 1;
        resetChars(chars);//重置所有值为-1

        int start = 0, head = start + 1;
        chars[s.charAt(0) - 'a'] = 0;//第0个字符对应的位置就是0了
        while (head < len) {
            code = s.charAt(head) - 'a';
            if (chars[code] > -1) {
                max = Math.max(head - start, max);
                start = chars[code] + 1;
                head = start + 1;
                resetChars(chars); //重置
                chars[s.charAt(start) - 'a'] = start;
            } else {
                chars[code] = head;//记录字符所在位置
                head++;
            }
        }

        //这个千万不能漏,本次1A失误全应此而起
        max = Math.max(head - start, max);

        return max;
    }

    void resetChars(int[] chars) {
        for (int i = 0, len = chars.length; i < len; i++) {
            chars[i] = -1;
        }
    }
}

ssnau
1.5k 声望98 粉丝

负能量职业打码师