Leetcode 3. 无重复字符的最长子串
3. 无重复字符的最长子串 - 力扣(LeetCode) (leetcode-cn.com)
思路 1 暴力穷举
1. 使用双指针遍历全部字符串,使用map存储已遍历的字符。
2. 在遍历过程中,如果当前index的字符已在map中存在,则此map长度为子串长度。
3. 保留返回最大的子串长度。
func lengthOfLongestSubstring(s string) int { length := len(s) if length == 0 { return 0 } res := 0 for left := 0; left < length; left++ { cur := make(map[byte]int) cur[s[left]] = 0 for right := left + 1; right < length; right++ { if _, ok := cur[s[right]]; ok { break } else { cur[s[right]] = 0 } } res = Max(res, len(cur)) } return res } func Max(val1, val2 int) int { if val1 > val2 { return val1 } else { return val2 } }
思路 2 使用map的滑动窗口
1. 定义left为左边界,right为右边界,res为最终结果。声明一个map用来存储字符和所在位置
2. 对s进行遍历,如果右边界指向的字符没有在map中,则将此字符放入map中,右边界右移。如果此字符已经在map中存在,则将左边界移到上一次出现此字符位置的下一个。
3. 当前长度=右边界-左边界+1
4. 最长长度:对每个窗口的长度进行比较,res保留最大的值
func lengthOfLongestSubstring(s string) int { length := len(s) if length == 0 { return 0 } left, right, res := 0, 0, 0 curMap := make(map[byte]int) for right < length { if _, ok := curMap[s[right]]; !ok { curMap[s[right]] = right } else { if curMap[s[right]]+1 >= left { left = curMap[s[right]] + 1 } curMap[s[right]] = right } res = Max(res, right-left+1) right++ } return res } func Max(val1, val2 int) int { if val1 > val2 { return val1 } else { return val2 } }
思路 3 不使用map的滑动窗口
1. 定义变量start当前子串的左边界,temp记录当前子串的长度,res保存最后的结果。
2. 右边界:对s进行遍历,开始位置为左边界,如果当前index的字符与左边界的字符不相同,则右边界等于当前index
3. 左边界:对s进行遍历,左边界需小于右边界, 如果在遍历过程中的index位置的字符和左边界所在的字符相同,左边界向右移动一位。
4. 当前长度:若符合要求,当前长度=右边界-左边界+1。若不符合要求,当前长度=右边界-左边界
5. 最长长度:对每个窗口的长度进行比较,res保留最大的值
func lengthOfLongestSubstring(s string) int { length := len(s) if length == 0 { return 0 } start, res := 0, 0 for i := 0; i < length; i++ { temp := i - start + 1 for j := start; j < i; j++ { if s[i] == s[j] { temp = i - start start = j + 1 break } } res = Max(res, temp) } return res } func Max(val1, val2 int) int { if val1 > val2 { return val1 } else { return val2 } }