字节跳动2018.9.9笔试 最长不重复子串

题目描述

给定一个字符串,请找出其中无重复字符的最长子字符串的长度。例如,“abcabcbb”,其无重复字符的最长子字符串实“abc”,其长度为3。“bbbbb”,其无重复字符的最长子字符串是“b”,长度为1。
此题是leetcode第三题原题。

本人思路

这里写图片描述
以上图为例,已经扫描到了abc了:
如果循环到了字符a,与当前扫描到的字符串中的a重复了,那么新的字符串就应该从a之后开始到当前循环字符。
如果循环到了字符b,与当前扫描到的字符串中的b重复了,那么新的字符串就应该从b之后开始到当前循环字符。

如果循环到了字符d,与当前扫描到的字符串中每个字符都不重复,那么新的字符串就应该从起始位置到当前循环字符。

代码

s = input()
n = len(s)

temp = []#存储当前扫描到的无重复最长子串
maxleng = 0 

for i in range(n):
    if(s[i] not in temp):#如果不在temp里就添加进去
        temp.append(s[i])
    else:#如果在里面,查看temp的长度是否比maxleng大
        if len(temp)>maxleng:
            maxleng = len(temp)
        index = temp.index(s[i])#获得当前重复的索引
        temp = temp[index+1:len(temp)]#新的temp是从重复字符之后开始
        temp.append(s[i])#再添加当前重复字符
if len(temp)>maxleng:#计算最后一次
    maxleng = len(temp)
print(maxleng)

但此代码有个弊端,就是需要temp数组来存当前扫描到的无重复子串,实际是不需要的。

最优思路

上LeetCode提交我的代码,运行时间124ms,打败了44%的人,可见我这个算法之差啊。但由于我提交的代码是python3,在LeetCode里面也只能看见python3里面的最优代码(80ms),下面我将对最优代码进行讲解。

class Solution:
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        start, longest, store = 0, 0, {}
        for i, c in enumerate(s):
            if c not in store:
                store[c] = i
            else:#当前c已经出现过了,但不一定在当前扫描到的无重复子串中
                #记录下当前c之前位置扫描到无重复子串的长度
                longest = max(longest, i - start)
                #更新无重复子串的开始位置,为下一次记录作好准备
                #如果当前c不在当前扫描到的无重复子串中,start不会更新
                #因为这种情况下,store[c] + 1 <= start
                start = max(start, store[c] + 1)
                #更新每个字符的最新位置
                store[c] = i
        longest = max(longest, len(s) - start)#记录最后一次
        return longest

此代码相比我的代码,优点在于不需要temp数组存储当前扫描到无重复子串,而是用start记录无重复子串的开始索引。

但是代码的思想和我的是很类似的。

和最优代码的进入else的条件不一样,我是在temp里有重复的就进入,所以无重复子串的起始位置肯定会更新;最优代码是只有字符是第二次出现就进入else,但不一定会更新无重复子串的起始位置。

start索引记录无重复子串的起码位置,i记录的是i-1是无重复子串的终止位置。我的代码中,是根据当前字符是否与temp有重复,如果有就进入else,进入else后起始位置start必更新。最优代码中,是根据当前字符是否出现过,如果出现过就进入else,进入else后起始位置start不一定更新,因为有可能当前字符上一次出现索引在start前面,这样的话start就不会更新。

start更新后,就为下一次进入else作好了准备,下一次执行longest = max(longest, i - start)i - start则就是下一次扫描到的无重复子串的长度。

再分析终止位置吧,当循环变量到了i时,终止位置则为I-1,看我画的第一个图就能明白。

posted @ 2018-09-11 13:19  allMayMight  阅读(85)  评论(0编辑  收藏  举报