头条2019校招笔试题 第一题 最长无重复子串:leetcode3-Longest Substring Without Repeating Characters

leetcode3-Longest Substring Without Repeating Characters

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.

头条题:
给定一个字符串,输出 最长无重复子串的长度。
输入:

abcabcbb

输出:

3

第一个思路:
创建一个字典zs_dic来装最长无重复子串里的字符,里面格式是 字符:字符在原始字符串的位置。字典的好处在于索引的复杂度是O(1),位置是为了后面删元素的时候好索引。
start和end指针用来记录子串的开头(字典的起始字符)和结尾(字典的结束字符)。

当出现dic里不存在的元素后,接着要删除字典里 原始字符串从start位置 到 dic里面该字符在原始字符串的位置 的所有字符。每删除一个,start+1,向后挪动,直到指向重复元素的后一个字符。
举个例子:
‘abebf’
当start指向a,end一直累加到指向第二个b时结束添加dic的循环,dic里的元素{a,b,e},
因为b在dic里出现了,要删掉字典里包括b及b之前的字符,也就是b,a。这时,就能利用到字典里每个键的值(位置)。删掉ba后dic变成{e},start每删掉一个就要+1,这样就刚好指到e,也就是dic起始元素的位置。
现在end还是指向b,就能重新将b加入到字典里,f又加到字典里。最后得到字典{e,b,f}。
子串更新后是nmax=3
注意,这个dic里记录的最长无重复子串,nmax即是子串的长度。
代码:

def Maxlens(s):
    start=end=0
    #dic key:字符 value:字符的索引
    zs_dic={}
    nmax=0
    while(endendand s[end] not in zs_dic):
            zs_dic[s[end]]=end
            end=end+1
        #count记录不重复子串的长度
        count=end-start
        nmax=max(count,nmax)
        if (end != len(s)):
            for i in range(zs_dic[s[end]],start-1,-1):
                del zs_dic[s[i]]
                start=start+1
    return nmax

第二个思路2:
kdic用来记录目前出现过的字符(不存在重复)。kdic[astr[i]] = i,键表示字符,值表示字符在原始字符串的位置。
begin记录子串的起始位置。
对原始字符串从头开始扫描每一个字符,如果字符在kdic出现过了,且字符串的初始值begin要重新赋值到重复字符+1
举个例子:
‘abebf’
kdic是{a:0,b:1,e:2},i=3时指向b,b出现在kdic里,且begin=0<=kdic[b]=1的位置,表示指针要重新赋值。于是把kdic[b]+1的位置,也就是b后面一个字符f的位置赋值给begin,现在begin就指向了f。最大长度就是(i-begin+1)

def Maxlens1(astr):
    begin = num = 0
    kdic = {}
    for i in range(len(astr)):
        if(astr[i] in kdic and begin <= kdic[astr[i]]):
            begin = kdic[astr[i]] + 1
        else:
            num = max(num, i - begin + 1)
        kdic[astr[i]] = i
    return num

你可能感兴趣的:(python)