题目描述:
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其
长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b"
,所以其长度为 1。
示例 3:
输入: "pwwkew" 输出: 3 解释: 因为无重复字符的最长子串是"wke"
,所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke"
是一个子序列,不是子串。
题目解析:这道题不能用暴力法循环,会超时,但是我还是会贴出暴力法的代码,虽然过不了,但是比较好理解。这道题我是用滑动窗口做的,对于滑动窗口,下面引用LeetCode官方题解的描述:
滑动窗口是数组/字符串问题中常用的抽象概念。 窗口通常是在数组/字符串中由开始和结束索引定义的一系列元素的集合,即 [i, j)[i,j)(左闭,右开)。而滑动窗口是可以将两个边界向某一方向“滑动”的窗口。例如,我们将 [i, j)[i,j)向右滑动 11 个元素,则它将变为 [i+1, j+1)[i+1,j+1)(左闭,右开)。
下面给出暴力法的C++代码:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int len=s.length();
int cnt=0,i,j,k,flag=0,result[len+5];
string x;
int MAX=0;
if(s==""){return 0;}
if(s.length()==1){return 1;}
for(i=0;i<len;i++){
x = "";
for(j=i;j<len;j++){
flag = 0;
for(k=0;k<x.length();k++){
if(s[j]==x[k]){flag=1;break;}
}
if(flag==0){x = x + s[j];}
if(j==s.length()-1||flag==1){
result[cnt++]=x.length();
break;
}
}
}
for(i=0;i<cnt;i++){
if(result[i]>MAX){MAX=result[i];}
}
return MAX;
}
};
对于暴力法,我想官方的描述很恰当:
假设我们有一个函数 boolean allUnique(String substring)
,如果子字符串中的字符都是唯一的,它会返回 true,否则会返回 false。 我们可以遍历给定字符串 s
的所有可能的子字符串并调用函数 allUnique
。 如果事实证明返回值为 true,那么我们将会更新无重复字符子串的最大长度的答案。
暴力法的时间复杂度是非常糟糕的O(n^3),所以会超时,下面给出利用滑动窗口写的C++和python代码:
C++完整代码如下:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int i = 0,j = 0, n = 0, ans= 0;
set<char> cont;//定义一个set类型的变量
n = s.size();
set<char>::iterator iter;//定义一个set类型的迭代器
while(i< n && j<n){
if( (iter=cont.find(s[j])) != cont.end() ){//如果迭代器所存储的字符存在于滑动窗口中,i向后移动一位
cont.erase(s[i++]);
}
else { //如果不在,j向后移动一位
cont.insert(s[j++]);
ans = max(ans, j-i);//获取最长的字串的长度
}
}
return ans;//返回最终结果
}
};
可能会有朋友对if后面的判断条件有所疑惑,这里给出我的理解:set类型的find函数会返回一个迭代器(find的参数是你想要寻找的变量),如果找到,返回非空的迭代器,如果未找到,返回空值,而end()函数返回的也是空值,所以if的判断条件的意思是,如果find函数返回的不是空值(即end()函数的返回值),那么说明在子串中找到了这个字符,“窗口”的左边界向右移动一位。
代码执行结果:
执行用时 : 76 ms, 在Longest Substring Without Repeating Characters的C++提交中击败了31.23% 的用户
内存消耗 : 15.9 MB, 在Longest Substring Without Repeating Characters的C++提交中击败了42.30% 的用户
Python完整代码如下:
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
n = len(s)
i = 0
j = 0
ans = 0
it = ""
cont = ""
while i<n and j<n:
if s[j] not in cont:
cont += s[j]
j += 1
ans = max(ans,len(cont))
else:
cont = cont[i+1:]
return ans
python用的也是滑动窗口,这里就不详细解释了。
代码执行结果:
执行用时 : 112 ms, 在Longest Substring Without Repeating Characters的Python3提交中击败了67.45% 的用户
内存消耗 : 13 MB, 在Longest Substring Without Repeating Characters的Python3提交中击败了98.17% 的用户
如果有写的不对的地方,还请各位朋友批评指正。