「这是我参与2022首次更文挑战的第29天,活动详情查看:2022首次更文挑战」
无重复字符的最长子串 Longest substring without repeating characters
LeetCode传送门3. 无重复字符的最长子串
题目
给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串 的长度。
Given a string s, find the length of the longest substring without repeating characters.
Example:
Input: s = "abcabcbb"
Output: 3
Explanation: The answer is "abc", with the length of 3.
Input: s = "bbbbb"
Output: 1
Explanation: The answer is "b", with the length of 1.
Input: s = "pwwkew"
Output: 3
Explanation: The answer is "wke", with the length of 3.
Notice that the answer must be a substring, "pwke" is a subsequence and not a substring.
Constraints:
- s consists of English letters, digits, symbols and spaces.
解题思路
暴力破解
首先我想到的第一种方法就是直接进行两次for
循环,然后第一次for
为子串的首字母,第二次for
为遍历字符串,把每次遍历结果放到res
数组中,直到遇到重复的元素,停止遍历,然后取出最长的字串和当前res
的长度,并把res
设置为空。
代码如下:
function lengthOfLongestSubstring(s: string): number {
// 暴力破解
let res = [];
let max = 0;
for(let i = 0;i < s.length; i ++) {
for(let j = i;j < s.length;j ++) {
if(res.includes(s[j])) {
max = Math.max(max, res.length);
res = []
break;
} else {
res.push(s[j])
}
}
}
return Math.max(max, res.length);
}
时间复杂度
: 其中n为字符串的长度。
滑动窗口法
上面的解题没有考虑到上一次找到的最长子字符串对下一次遍历产生的影响,因此时间复杂度非常高。我们考虑一下,如果我们从头遍历字符,然后遇到第一个重复的字符,那么我们只要去除掉子字符串重复字符前的字符即可,重复字符后的内容因为已经经过遍历检查我们可以不用再考虑其唯一性,直接使用即可。
根据上面的思考。在编程中我们用如下步骤来完成对应的编程工作
- 把字符串转换为数组,并遍历
- 把每次遍历的值进行判断
- 如果结果数组
res
中没有该值,证明该值不和前面的值重复,把它放入数组中 - 如果结果数组
res
中有该值,证明该值和前面的值重复,先从res
数组长度和max
直接找到大值,作为max
的新值。再从res
的头部开始找,直到找到 该重复元素为止,删除数组中重复元素和之前的所有字符。
- 如果结果数组
- 对max和
res
的长度进行比较,返回大值,即为我们想要的结果。
代码如下:
function lengthOfLongestSubstring(s: string): number {
// 滑动窗口法
const arr = s.split('');
const res = []
let max = 0;
arr.forEach((item, index) => {
if(res.includes(item)) {
max = Math.max(max, res.length);
while(res[0] !==item) {
res.shift()
}
res.shift()
res.push(item);
} else {
res.push(item)
}
})
return Math.max(max, res.length);
};
时间复杂度
O(n): n为字符串的长度
这就是我对本题的解法,如果有疑问或者更好的解答方式,欢迎留言互动。