zoukankan      html  css  js  c++  java
  • leetcode算法:3.无重复字符的最长子串

    无重复字符的最长子串

    给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

    示例 1:

    输入: "abcabcbb"
    输出: 3 
    解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
    

    示例 2:

    输入: "bbbbb"
    输出: 1
    解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
    

    示例 3:

    输入: "pwwkew"
    输出: 3
    解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
         请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
    

    思考

    考虑空间复杂度

    1. 要求空间复杂度O(1)
    2. 允许空间复杂度O(n)

    解答

    • 对于要求空间复杂度O(1)的这种情况,需要双层循环暴力搜索。
    • 对于允许空间复杂度O(n)的这种情况,空间换时间,可以达到时间复杂度O(n)。思路是用一个指针指示不重复字符串的开始位置,利用这个指针计算当前字符串长度,然后从第一个字符串开始搜索,每搜索一个字符串时查看是否有重复,没有重复继续下一个并更新不重复字符长度,有则将指针移动前面那个重复字符的下一字符处。

    举个例子: 对于abcabc,首先指针p指向index为0的a,然后循环遍历字符串,遍历到index为1的b时,指针p指向a(index为0),此时未出现重复字符串,当前子串最大长度为index(b) - p = 1-0+1=2,然后继续遍历移动字符c,同理,此时index为2(字符c),指针p指向a(index为0),当前子串最大长度为index(b) - p = 1-0+1=2,继续遍历到字符a,此时a重复,从map中查询到前面a的index为0,则为保持不重复字符串的特性,需将指针p移到到a的下一位,因此p=index(a)+1。每次都计算最长子串长度,直到遍历结束。

    package algo
    
    func lengthOfLongestSubstring(s string) int {
    	if len(s) < 1 {
    		return 0
    	}
    	if len(s) == 1 {
    		return 1
    	}
    
    	var (
    		charMap               = make(map[int32]int)
    		maxLength             = 0
    		uniqueCharStringStart = 0
    	)
    
    	for index, each := range s {
    		// 判断字符是否重复
    		if at, ok := charMap[each]; ok {
    			// 重复则将不重复字符串首字符位置指示符移动到重复字符后
    			if at >= uniqueCharStringStart {
    				uniqueCharStringStart = at + 1
    			}
    		}
    
    		if index-uniqueCharStringStart+1 > maxLength {
    			maxLength = index - uniqueCharStringStart + 1
    		}
    
    		charMap[each] = index
    	}
    
    	return maxLength
    }
    

      

    单元测试

    package algo
    
    import (
    	"testing"
    )
    
    func TestLengthOfLongestSubstring(t *testing.T) {
    	s1 := "abcdabcd"
    	s2 := "abcabc"
    	s3 := "aaaaaa"
    	s4 := "abcddcba"
    	s5 := "abcdefg"
    	s6 := ""
    	s7 := " "
    	s8 := "  "
    	s9 := "dvdf"
    
    	if lengthOfLongestSubstring(s1) != 4 {
    		t.Fatal()
    	}
    	if lengthOfLongestSubstring(s2) != 3 {
    		t.Fatal()
    	}
    	if lengthOfLongestSubstring(s3) != 1 {
    		t.Fatal()
    	}
    	if lengthOfLongestSubstring(s4) != 4 {
    		t.Fatal()
    	}
    	if lengthOfLongestSubstring(s5) != 7 {
    		t.Fatal()
    	}
    	if lengthOfLongestSubstring(s6) != 0 {
    		t.Fatal()
    	}
    	if lengthOfLongestSubstring(s7) != 1 {
    		t.Fatal()
    	}
    	if lengthOfLongestSubstring(s8) != 1 {
    		t.Fatal()
    	}
    	if lengthOfLongestSubstring(s9) != 3 {
    		t.Fatal()
    	}
    }
    

      

  • 相关阅读:
    处理i18n国际电话区号的代码实践
    iOS 万能跳转界面方法 (runtime实用篇一)
    URI跳转方式地图导航的代码实践
    iOS @IBDesignable和@IBInspectable
    我的iOS高效编程秘诀—坚持编程习惯
    如何手动解析CrashLog
    小心别让圆角成了你列表的帧数杀手
    iOS开发之使用Runtime给Model类赋值
    POP介绍与使用实践(快速上手动画)
    NSString&NSMutableString常用操作梳理
  • 原文地址:https://www.cnblogs.com/pluse/p/13363727.html
Copyright © 2011-2022 走看看