大家好,我是散步coding, 最近在整顿2022年LeetCode高频算法面试题 ,感觉好的, 能够点赞、珍藏哈。同时有补充的也欢送大家给出反馈。本文首发于公众号: 散步coding

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

<font color=#FF000 >题目难度: ★★★, 中等</font>

示例 1:

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

示例 2:

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

示例 3:

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

提醒:

  • 0 <= s.length <= 5 * 104
  • s 由英文字母、数字、符号和空格组成

代码实现

tips: 以下代码是应用Go代码实现的不同解法, 文章最初能够看C++、C、Java、Python实现

1、滑动窗口

  • 1)、滑动窗口由左右两个指针(start, end)组成,其起始地位均为0。
  • 2)、窗口挪动时,让左指针star不变,仅挪动右指针end,不断扩大子串。
  • 3)、子串中是否存在反复字符,咱们应用map存储字符呈现的地位。
  • 4)、<font color=#FF000 >右指针end的下一个字符是否曾经存在于map中,若是,则左指针start右移到该字符呈现地位的下一位(因为从左指针start到这一位两头是必然有反复的);否则反复步骤2。</font>
  • 5)、每次刷新窗口时,都要对窗口长度进行计算,若大于原来标记的最大窗口长度,则进行更新。

另外,要留神一些边界条件,如字符串长度不能为0,否则将导致数组越界;

这样,通过一次遍历就可能失去后果,工夫复杂度为O(n)。

图解过程

<font color=#FF000 >步骤1、</font>

<font color=#FF000 >步骤2、</font>

<font color=#FF000 >步骤3、</font>

<font color=#FF000 >步骤4、</font>

<font color=#FF000 >步骤5、</font>

<font color=#FF000 >步骤6、</font>

func lengthOfLongestSubstring(s string) int {   if len(s) == 0 {      return 0   }   start, end, max := 0,0,0   m := map[byte]int{}   for ; end < len(s); end++{      if _,ok := m[s[end]]; ok {         if m[s[end]] + 1 >= start { // 针对s是"abba", end是3(最初一个a), start是2(第二个b), m[s[end]]=m['a']是0,所以须要更新start            start = m[s[end]] + 1            }      }      m[s[end]] = end      if end - start + 1 > max {         max = end - start + 1      }   }   return max}

执行后果:

其余语言版本

C++

// 滑动窗口// 工夫复杂度: O(len(s))// 空间复杂度: O(len(charset))class Solution {public:    int lengthOfLongestSubstring(string s) {        int freq[256] = {0};        int l = 0, r = -1; //滑动窗口为s[l...r]        int res = 0;        // 整个循环从 l == 0; r == -1 这个空窗口开始        // 到l == s.size(); r == s.size()-1 这个空窗口截止        // 在每次循环里逐步扭转窗口, 保护freq, 并记录以后窗口中是否找到了一个新的最优值        while(l < s.size()){            if(r + 1 < s.size() && freq[s[r+1]] == 0){                r++;                freq[s[r]]++;            }else {   //r曾经到头 || freq[s[r+1]] == 1                freq[s[l]]--;                l++;            }            res = max(res, r-l+1);        }        return res;    }};

执行后果:

Java

class Solution {    public static int lengthOfLongestSubstring(String s) {    Map<Character, Integer> charIndex = new HashMap<>(s.length());    int start =0, maxLength = 0, length = 0;    for (int i =0; i < s.length(); i++) {        Character ch = s.charAt(i);        Integer lastIndex = charIndex.get(ch);        if (Objects.nonNull(lastIndex) && charIndex.get(ch) >= start) {            start = lastIndex + 1;            length = i - start + 1;        } else {            length += 1;        }        maxLength = length > maxLength ? length : maxLength;        charIndex.put(ch, i);    }    return maxLength;  }}

执行后果:

几种语言运行成果比照