目录
- 1.题目以及测试用例:
- 2.解题思路:
- 3.代码实现:
- 4.复杂度说明:
1.题目以及测试用例:
题目说明:给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。示例 2:
输入: s = “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。示例 3:
输入: s = “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。*
2.解题思路:
解析:
本题使用滑动窗口的思想可以进行解决
首先,定义三个变量:left
表示当前滑动窗口的左边界,初值为0
;maxLen
表示最长不重复子串的长度,初值为0
;map
是一个Map对象,用来记录字符和字符对应的下标。
然后,通过一个循环遍历字符串s
中的每个字符。在每次循环中,首先判断当前字符s[i]
是否在map
中存在,并且它的下标大于等于left
。如果满足条件,则将left
移动到s[i]
上次出现的下标的下一个位置,确保滑动窗口中不包含重复的字符。
接下来,更新map
中s[i]
的值为当前下标i,表示最近一次出现s[i]
的位置。然后,计算当前滑动窗口的长度i - left + 1
,并与maxLen
比较,取较大值作为新的maxLen
。
最后,循环结束后,返回maxLen
作为结果,即最长不重复子串的长度。
3.代码实现:
代码:
/**
* @param {string} s
* @return {number}
*/
var lengthOfLongestSubstring = function(s) {
let left = 0;
let maxLen = 0;
let map = new Map();
for (let i = 0; i < s.length; i++) {
if (map.has(s[i]) && map.get(s[i]) >= left) {
left = map.get(s[i]) + 1;
}
map.set(s[i], i);
maxLen = Math.max(maxLen, i - left + 1);
}
return maxLen;
};
4.复杂度说明:
时间复杂度和空间复杂度解析:
时间复杂度是O(n)
,其中n
是输入字符串的长度。这是因为代码中使用了一个循环来遍历字符串中的每个字符。
在循环中,大部分操作的时间复杂度都是O(1)
,例如对map
的操作、取最大值、更新maxLen
等。这些操作的时间复杂度不随输入规模增大而改变。
因此,循环的时间复杂度主要取决于字符串的长度n
。每个字符都会被遍历一次,所以循环的时间复杂度是O(n)
。
同时,代码中使用了一个map
来记录字符和字符对应的下标,所以空间复杂度是O(k)
,其中k
是字符串中不重复字符的个数。在最坏的情况下,字符串中的每个字符都不相同,因此k
最多为n
。所以空间复杂度可以近似看作是O(n)
。