这种方法虽然易于理解,但是由于时间复杂度问题,运行超时。

现在再分析一下题目,是否有必要计算以每个字符开头的最长子字符串?

答案是不必要的。比如说对于字符串abcdedfghi从a开始往后进行判断,则遇到第二个d的时候会发现与前面的d重复了,判断停止,那么以a开头的最长子字符串为abcde,然后以一个新的字母开头找最长的子字符串。按照上面的方法,接下来会以b为开头找其最长子字符串。但是你会发现找到的最长子字符串肯定比以a开头的最长子字符串要短,原因是后面重复的元素位置没有变,而从b或c开始相当于把不重复的部分截断了。所以如果要找到可能更长的子字符串,必须要从与当前字符重复的字符往后的一个字符位置开始找,在本例中就是要从e开始找,才有可能找得到比以a开头的最长子字符串更长的子字符串。

这样,便可以通过找与当前字符重复的前一字符的位置来避免第二层的for循环,将时间复杂度缩短为$O(n)$

通过双指针能够实现上面的功能,左右指针共同维护一个没有重复字符的子字符串,每当没有重复字符时,右指针一直往右移动;有重复字符时左指针往右移动直到左右指针之间没有重复字符。

right += 1

上面的方法虽然能够AC但是每次遇到重复元素时左指针往右一步一步地移动并删除元素的操作会比较慢,因此可以 通过 HashTable 存储每个元素的最大下标,遇到重复元素的时候判断前一重复元素位置的下标是否大于当前左指针位置,若是则更新左指针,否则不更新;同时更新HashTable 当前重复元素的下标。下面是实现的代码