共计 2136 个字符,预计需要花费 6 分钟才能阅读完成。
大家好,我是散步 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; | |
} | |
} |
执行后果:
几种语言运行成果比照
正文完