给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
示例 4:
输入: s = ""
输出: 0
提示:
0 <= s.length <= 5 * 104
s 由英文字母、数字、符号和空格组成
来源:力扣(LeetCode)
解题代码
/**
* @param {string} s
* @return {number}
*/
var lengthOfLongestSubstring = function(s) {
let arr = new Array()
let max = 0
for (let i = 0; i < s.length; i++) {
let index = arr.indexOf(s[i]) //
if (index !== -1) { //在数组中找到了和当前一样的字符
arr.splice(0, index + 1) //切割掉
}
arr.push(s[i]) //无论找没找到都要push进入arr
max = Math.max(arr.length, max) //取最大值
}
return max
};
思路:滑动窗口
设一个滑动窗口数组arr
,用数组每次记录下最长符合要求的子串,利用js的Array.prototype.splice()方法
切割相同字符之前的部分
图解
图解abcabcbb
┌─┐
│a│b c a b c b b # max = 0 , arr.length =1 取最大得: max = 1
└─┘
┌───┐
│a b│c a b c b b # max = 1 , arr.length =2 取最大得: max = 2
└───┘
┌─────┐
│a b c│a b c b b # max = 2 , arr.length =3 取最大得: max = 3
└─────┘
┌─────┐
a│b c a│b c b b # max = 3 , arr.length =1 取最大得: max = 3
└─────┘
┌─────┐
a b│c a b│c b b # max = 3 , arr.length =1 取最大得: max = 3
└─────┘
┌─────┐
a b c│a b c│b b # max = 3 , arr.length =1 取最大得: max = 3
└─────┘
┌───┐
a b c a b│c b│b # max = 3 , arr.length =1 取最大得: max = 3
└───┘
┌─┐
a b c a b c b│b│ # max = 3 , arr.length =1 取最大得: max = 3
└─┘
类似地:
图解pwwabw
┌─┐
│p│w w a b w
└─┘
┌───┐
│p w│w a b w
└───┘
┌─┐
p w│w│a b w
└─┘
┌───┐
p w│w a│b w
└───┘
┌─────┐
p w│w a b│w
└─────┘
┌─────┐
p w w│a b w│
└─────┘
总结与反思
- 问题一:为什么不管在数组中找得到还是找不到当前字符,都要push字符进入数组?
- 答:只有这样才能让数组滚动到最后,所以也必须逐个记录字符,让我们能找到不含有重复字符的子串
- 问题二:为什么找到了字符之后要删除数组的前半部分?
- 答:首先你得知道arr的作用是什么,虽然删除了前半部分有可能使我们的arr数组长度变小,但是对于当前情况来说,你已经得到了最大的数组长度,不用担心缩短数组的长度,arr的任务是:它不是用来记录最长字串的数组!而是用来记录每两个相同字符之间的长度