[LeetCode] Longest Substring Without Repeating Characters

来源:互联网 发布:中俄大桥 知乎 编辑:程序博客网 时间:2024/06/13 08:31

关于LeetCode更多详细的代码,请参考https://github.com/Crazykev/Leetcode


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.


分析

思路1
这道题目的思路很直观,如果我们从头到尾去遍历字符串,将目前为止最长的子串记录下来(我们可以只记录起止两个指针或者下标来表示这段子串),每遇到一个字符就判断该字符是否存在于我们已经记录的子串中,如果已经存在,就更新我们已经记录的子串最长值,并且将子串的起始位置更新为已存在字符的后一个字符,继续往下遍历,直至遍历完成。算法时间复杂度是O(n),空间是O(k),k是字符范围长度。
这个思路中有一个关键问题需要解决,就是如何能快速判断当前字符是否已经存在。这里我们可以继续使用hash表(最直接和特殊的方式是数组,hash函数的结果等于当前值),将已经存在的字符的下标存入hash表中,每次进行检索的时候便可以快速搜索到,在每次重新找下一段子串的时候都需要清理前面无用子串在hash表中存入的字符位置。
golang代码

golang代码

思路1

这份代码做了前提假设,比如字符串中的字符utf-8码是位于[0-256),也就是基本字符ascii码。

func lengthOfLongestSubstring(s string) int {    hashTable := [256]int{}    var (        start   int = 0        longest int = 0        curLen  int = 0    )    if len(s) == 0 {        return 0    }    for curIndex, curChar := range s {        if oldIndex := hashTable[curChar] - 1; oldIndex != -1 {            if curLen > longest {                longest = curLen            }            curLen = curIndex - oldIndex            for i := start; i < oldIndex; i++ {                hashTable[s[i]] = 0            }            start = oldIndex + 1            hashTable[curChar] = curIndex + 1            continue        }        hashTable[curChar] = curIndex + 1        curLen++    }    if curLen > longest {        longest = curLen    }    return longest}

目前,这份代码目前是这道题目golang提交中最快的一批,6ms。
其实后来思考一下,这个实现还是有可提升空间的,在往后面遍历的时候,我们可以算出当前可能获得的最长子串长度是已经记录的长度加上未遍历字符串的长度,如果已经记录的最长不重复子串长度已经超过这个长度了,就不需要继续遍历了,非常常规的剪枝思路。

1 0
原创粉丝点击