【LeetCode】3 、Longest Substring Without Repeating Characters
题目等级:Medium
题目描述:
Given a string, find the length of the longest substring without repeating characters.
Example 1:
Input: "abcabcbb"
Output: 3
Explanation: The answer is "abc", with the length of 3.
Example 2:
Input: "bbbbb"
Output: 1
Explanation: The answer is "b", with the length of 1.
Example 3:
Input: "pwwkew"
Output: 3
Explanation: The answer is "wke", with the length of 3.
Note that the answer must be a substring, "pwke" is a subsequence and not a substring.
题意:给定一个字符串,找到其中不含重复字符的最长子串的长度,要注意子串和子序列的区别。
解题思路:
一般对于这种稍微复杂一些的题目,首先可以想到的是最基础的暴力解法,然后我们可以在暴力解法的基础上思考相应的改进和提升效率的算法,针对本题我们给出以下三种解法。
解法一:Brute Force暴力解法
暴力解法自然是最直观的,既然是求不含重复字符的最长子串,我们可以通过穷举所有的子串,判断其中是否含有重复字符,并记录最大长度。假设我们现在有一个函数能判断一个字符串中是否包含重复字符,然后只需要一个两层循环枚举所有的子串,即可得到结果。
那么这个判断一个字符串是否包含重复字符的函数该怎么实现呢,首先要判断一个字符串是否包含重复字符,总得每一个字符都比较过才能知道重复与否,因此大致这个算法应该是O(n)复杂度。再进一步思考,要判断是否重复,集合不正好是不包含重复元素的数据结构吗,因此,只需用一个set保存之前的元素,我们就可以知道是否重复了。
对于这个暴力解法,首先要穷举所有的子串需要两层循环,每个子串判断重复与否还需要一层循环,因此,整体时间复杂度是O(n^3),由于使用了一个Set,空间复杂度为O(n)。
然而,我们把以下的代码实现在LeetCode上提交,会发现提示Time Limit Exceeded,因为超时无法通过。
class Solution {
public int lengthOfLongestSubstring(String s) {
if(s==null || s.length()==0)
return 0;
int len=s.length();
int res=1;
for(int i=0;i<len;i++){
for(int j=i+1;j<len;j++){
if(allUnique(s,i,j))
res=Math.max(res,j-i+1);
}
}
return res;
}
public boolean allUnique(String s,int i,int j){
Set<Character> set=new HashSet<>();
for(;i<=j;i++){
char c=s.charAt(i);
if(set.contains(c))
return false;
set.add(c);
}
return true;
}
}
解法二:滑动窗口解法
暴力法由于超时无法通过,因此我们必须改进算法,提升时间效率。回过头来,我们再看暴力解法,可以发现实际上这个解法做了很多重复的和不必要的工作,主要体现在以下两个方面:
(1)分别判断每一个子串是否重复,这里面是有很多重复的工作的,实际上子串和子串之间不是孤立的,是有联系的。比如,如果我们已经判断了字符串str中从i到j(i和j是下标)是不包含重复字符的,那么在判断从i到j+1时,完全没必要从头在来判断这个子串,因为我们只需要知道第j+1个字符是否在从i到j中出现过就可以了。
(2)如果我们已经判断了字符串str中从i到j(i和j是下标)是包含重复字符的,那么以第i个字符开始,以第j个字符之后的所有字符结尾的字符串都没必要再判断了,因为它一定也是包含重复字符的。此时直接增大i的值就可以了。
综合以上两点,实际上我们不难得出,这实际上就是一个滑动窗口从前向后移动的过程,如下图所示:

由此,我们可以得到如下所示的代码实现,即滑动窗口解法。其中只有一层循环,并且最坏的情况下循环次数为2n次(即j先加到最大,然后i由逐步加大,各需要n次),所以,时间复杂度为O(2n),仍然用了一个set保存字符,所以空间复杂度为O(n)。
class Solution {
public int lengthOfLongestSubstring(String s) {
if(s==null || s.length()==0)
return 0;
int len=s.length();
int i=0,j=0;
Set<Character> set=new HashSet<>();
int res=0;
while(i<len&&j<len){
char c=s.charAt(j);
if(set.contains(c)){ //注意这里,并不只是i+1,对应的字符也要从集合中删掉
set.remove(s.charAt(i));
i++;
}else{
set.add(c);
res=Math.max(res,j-i+1);
j++;
}
}
return res;
}
}
解法三:改进的滑动窗口
解法二实际上已经将复杂度降到了O(n)级别,正如我们前面所说,要判断每个字符是否重复,最起码每个字符都要比较到,否则不可能知道重复与否,因此直观上我们应该有一个大概的认识:此题的算法很有可能应该是不会比O(n)更优了,当然这只是一个粗略的想法。
解法三实际上也就是针对解法二的一个地方进行了优化。考虑如下情况:

此时,j指向c,根据滑动窗口解法,前面的窗口中存在c,因此重复,此时应该i增大1,指向b,但是很明显,从b到j中还是包含重复的c,因此一定是仍然重复的,所以当遇到重复时,i没必要只加一,可以一步到位,直接定位到重复字符的下一个去,比如这里,可以直接指向d,因为前面无论哪个都包含c,都会重复。
因此,我们就可以得到对应的解法三,这里由于需要保存字符,还需要保存位置,因此必须将set改为Map<字符,下标>。这样,我们看到,实际上i是跳跃向前的,因此最坏情况下也只需要n次循环,时间复杂度由O(2n)降到了O(n),空间复杂度只是由set换为map,仍为O(n)。
代码如下:
class Solution {
public int lengthOfLongestSubstring(String s) {
if(s==null||s.length()==0)
return 0;
int len=s.length();
int i=0,j=0,res=0;
Map<Character,Integer> map=new HashMap<>();
while(j<len){
char c=s.charAt(j);
if(map.containsKey(c)){
i=Math.max(i,map.get(c)+1);
}
res=Math.max(res,j-i+1);
map.put(c,j);
j++;
}
return res;
}
}
除此之外,正如很多题中用到的,如果针对于一些特殊的字符集,比如ASCLL码,就可以用字符数组代替哈希表,字符的ASCII码作为下标,数组值为字符的位置。
总结
对于本题,这三种解法实际上正是LeetCode的题解中给出的,从暴力到比较巧妙的滑动窗口,再到对其进行改进,跳跃向前,时间复杂度逐步降低,这里,我认为重点不是如何解决这一道题,而是如何分析,从哪里能给改进,一步一步寻找最佳解法。
【LeetCode】3 、Longest Substring Without Repeating Characters的更多相关文章
- LeetCode 第 3 题(Longest Substring Without Repeating Characters)
LeetCode 第 3 题(Longest Substring Without Repeating Characters) Given a string, find the length of th ...
- 【LeetCode从零单排】No 3 Longest Substring Without Repeating Characters
题目 Given a string, find the length of the longest substring without repeating characters. For exampl ...
- Leetcode经典试题:Longest Substring Without Repeating Characters解析
题目如下: Given a string, find the length of the longest substring without repeating characters. Example ...
- LeetCode(3)Longest Substring Without Repeating Characters
题目: Given a string, find the length of the longest substring without repeating characters. For examp ...
- leetcode第三题Longest Substring Without Repeating Characters java
Longest Substring Without Repeating Characters Given a string, find the length of the longest substr ...
- leetcode第三题--Longest Substring Without Repeating Characters
Problem:Given a string, find the length of the longest substring without repeating characters. For e ...
- LeetCode解题笔记 - 3. Longest Substring Without Repeating Characters
Given a string, find the length of the longest substring without repeating characters. Examples: Giv ...
- LeetCode第三题—— Longest Substring Without Repeating Characters(最长无重复子字符串)
题目描述 Given a string, find the length of the longest substring without repeating characters. Example ...
- leetcode - 3、Longest Substring Without Repeating Characters
题目链接:https://leetcode.com/problems/longest-substring-without-repeating-characters/description/ 题目要求: ...
随机推荐
- YTU 2782: 用数字造数字
2782: 用数字造数字 时间限制: 1 Sec 内存限制: 128 MB 提交: 191 解决: 160 题目描述 输入一个3位以上的整数,求其中最大的数字最小的数字之间的差.例如:输入8729 ...
- 【Bzoj2260】【Bzoj4349】商店购物 & 最小树形图
目录 List Bzoj 2260 商店购物 Description Input Output Sample Input Sample Output Bzoj 4349 最小树形图 Descripti ...
- 【HDU 3068】 最长回文
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=3068 [算法] Manacher算法求最长回文子串 [代码] #include<bits/s ...
- bzoj 2276 [ Poi 2011 ] Temperature —— 单调队列
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2276 维护 l 递减的单调队列,队头的 l > 当前的 r 就出队,因为不能是连续一段 ...
- /lib/dracut/hooks/shutdown/30-dm-shutdown.sh
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAABVQAAAMACAIAAABEqXuoAAAgAElEQVR4nOydPWjryOK3VaZM8RYpU2 ...
- vuejs 中如何优雅的获取 Input 值
http://www.sunzhongwei.com/how-to-get-input-value-in-vuejs
- jquery模拟下拉框
<!DOCTYPE html> <html lang="en"> <head> <title>jquery模拟SELECT框< ...
- JS连续滚动幻灯片:原理与实现
什么是连续滚动幻灯片?打开一些网站的首页,你会发现有一块这样的区域:一张图片,隔一段时间滑动切换下一张:同时,图片两端各有一个小按钮,供你手动点选下一张:底部有一排小圆圈,供你选定特定的某帧图片.这就 ...
- [Apple开发者帐户帮助]九、参考(5)支持的功能(tvOS)
tvOS应用程序可用的功能取决于您的程序成员身份. 能力 ADP 企业 Apple开发者 应用程序组 相关域名 背景模式 数据保护 游戏中心 游戏控制器 HomeKit iCloud:Cl ...
- cocos creator学习
2019-05-30 22:23:27 按照前一节我发的教程做,大概了解了Cocos creator的基本布局 但是你发现你不好写代码(感觉视频没有提) 需要下载VS code软件,在其上进行编辑,教 ...