Go语言:LeetCode-无重复字符的最长子串

题目:给定一个字符串,请你找出其中不含有重复字符的最长字串的长度。
示例1:
输入:“abcabcbb”
输出:3
解释:因为无重复字符的最长子串是“abc",所以其长度为3.
示例2:
输入:”bbbbb"
输出:1
解释:因为无重复字符的最长子串是"b",所以其长度为1
示例3:
输入:“pwwkew"
输出:3
解释:因为无重复字符的最长子串是”wke",所以其长度为3。

请注意,你的答案必须是子串的长度,”pwke“是一个子序列,不是子串。

解法一:暴力穷举法。找出所给字符串所有的子串,然后以用 map 算出每个子串是否包含重复字符。这种解法比较容易想到和实现,但是时间复杂度也是很大的,当字符串很大时,暴力穷举法时不可取的。在LeetCode上提交也会超时。具体实现如下代码所示:

//RepeatCheck函数:用于检查n字符串s中是否有重复的字符
func RepeatCheck(s string) bool {
	//利用map存储字符串s中的每个字符
	var mapper map[byte]int
	mapper = make(map[byte]int)
	var i int
	for i = 0; i < len(s); i++ {
		mapper[s[i]]++
	}
	/*判断map的长度与字符串s的长度是否相等。如果不相等,
	说明有重复字符*/
	if len(mapper) == len(s) {
		return false
	}
	return true
}

func lengthOfLongestSubstring(s string) int {	
	//对长度为1的字符串进行特殊处理
	if len(s) == 1 {
		return 1
	}
	var i, j int
	var maxLen int
	/*两层循环获取字符串所有的子串*/
	for i = 0; i < len(s); i++ {
		for j = i + 1; j <= len(s); j++ {
			subStr := s[i:j]
			//判断每个子串是否有重复得分字符
			if RepeatCheck(subStr) == false {
				if len(subStr) > maxLen {
					maxLen = len(subStr)
				}
			}
		}
	}
	return maxLen
}

解法二:利用滑动窗口原理,先固定字符串左边,然后移动字符串右边,直到该子串出现重复字符就停止,然后在移动字符串左边的下一位。如此重复,大大减少了子串的搜索空间,从而减少了时间复杂度,提高了效率。
举个例子:字符串"abab",利用穷举法就需要算出 a,ab,aba,abab,b,ba,bab,a,ab,b.利用滑动窗口的思想,只需要算出a,ab,(aba,出现重复字符,接下来的子串不需要计算)b,ba,(bab,出现重复字符),a,ab,b。
具体实现如下代b码所示:

func lengthOfLongestSubstring(s string) int {
	if len(s) == 1 {
		return 1
	}
	var i, j int
	var maxLen int
	for i = 0; i < len(s); i++ {
		//利用mapper来计算从i到j的子串是否有重复字符
		
		var mapper map[byte]int
		mapper = make(map[byte]int)
		mapper[s[i]]++
		//j不断向右移动,直至遇到mapper中出现重复字符,即ok为true值
		for j = i + 1; j < len(s); j++ {
			_, ok := mapper[s[j]]
			mapper[s[j]]++
			/*当出现重复字符时,判断从i到j的子串长度是否比maxLen大,
			并停止对后面子串的搜索。
			*/
			if ok == true {
				if j-i > maxLen {
					maxLen = j - i
				}
				break
			}
		}
		//当来到字符串末尾时,进行特殊处理
		if j == len(s) {
			if j-i > maxLen {
				maxLen = j - i
			}
		}
	}
	return maxLen
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值