题目链接
给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串
的长度,“pwke” 是一个子序列,不是子串。
提示:
0
<
=
s
.
l
e
n
g
t
h
<
=
5
∗
1
0
4
0 <= s.length <= 5 * 10^4
0<=s.length<=5∗104
s
由英文字母、数字、符号和空格组成
解题思路
本题可以使用动态规划的思想,定义数组 dp[N]
,dp[i]
代表以第i
个字符s[i]
作为结束的最大子串长度。那么对于第i+1
个字符,会出现两种情况:
\qquad
- s[i+1]没有出现
在以s[i]结束的最大子串里面
\qquad
- s[i+1]出现
在以s[i]结束的最大子串里面
\qquad
对于第一种情况,直接将s[i+1]
加入以s[i]
为结束的最大子串即可。
\qquad
对于第二种情况,首先需要找到s[i+1]
上一次出现的位置pre
,pre
到i+1
的长度即为以s[i+1]
结束的子串的最大长度。
怎么找到s[i+1]
上一次出现的位置呢,我们可以使用C++的标准库map,更新map[s[i]]=i
即可。
解题代码
#include<iostream>
#include<string>
#include<map>
using namespace std;
class Solution {
public:
int lengthOfLongestSubstring(string s) {
if (s.length()==0) return 0;
map<char,int>counter;
int dp[int(s.length())+1];
for (int i=0;i<s.length();i++){
dp[i]=1;
}
counter[s[0]]=0;
int max_len = 1;
for(int i=1;i<s.length();i++){
if(counter.find(s[i])==counter.end()){
dp[i]=dp[i-1]+1;
}
else{
int pre = counter[s[i]];
if(pre<i-1-dp[i-1]+1){
dp[i]=dp[i-1]+1;
}
else{
dp[i]=max(dp[i],i-pre);
}
}
counter[s[i]]=i;
max_len=max(max_len,dp[i]);
}
//for (int i=0;i<s.length();i++){
// cout<<dp[i]<<" ";
//}cout<<endl;
return max_len;
}
};
int main(){
string s="pwwkew";
map<char,int>counter1;
for (int i=0;i<s.length();i++){
counter1[s[i]]+=1;
}
Solution so = Solution();
int res = so.lengthOfLongestSubstring(s);
cout<<res<<endl;
return 0;
}