跟我学:LeetCode刷题之3. 无重复字符的最长子串
导读
刷算法题需要一定的节奏,同样对待每一道算法题也需要认真的对待不可操之过急,否则会导致:算法虐我千万遍,我待算法如初恋!如果这句话是从对算法态度上说爱如初恋那必须得肯定你的态度,但如果是每一道算法题,反复都能虐你千万遍,那这个初恋的滋味肯定不好受。我们应该是面对新题对待如初恋,对待已经做过的题应该是勾勾手指,手到擒来的老司机,否则就是白刷。不仅浪费时间而且浪费精力,所以刷题必须讲究方式方法,建议反复阅读此文跟我学:LeetCode刷题大法。下面这里通过一张思维导图帮助大家整理这道题的思路。思维导图一方面罗列了本文的大纲,另一方面也是希望读者朋友可以保存图片至自己的复习资料里,以便随时通过该大纲去复习,注意关注标红的重点解法。
看题总结
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
1 | 输入: "abcabcbb" |
示例 2:
1 | 输入: "bbbbb" |
示例 3:
1 | 输入: "pwwkew" |
Related Topics
哈希表
双指针
字符串
Sliding Window
通过对题目的阅读,我们可以得出以下几个结论
- 题目类型为数组
- 要求是返回最长的不含重复字母的子串长度
- 输入的字符串可能为空串,输入判断
多解法及复杂度分析
解法一:暴力法,多重循环
首先希望读者能写出双重循环的模板代码,在此再次强调此代码是数组问题暴力法的套路墙裂建议背诵默写,如果还是不能随手写出回过头看一下此文跟我学:LeetCode刷题之1.两数之和,好了继续此问题的暴力解决法就是通过双重循环,加内部一层循环判断[i,j]之间的元素是否是唯一的,然后做相应的移动和记录最大值。注意此处的双重循环的i,j范围,是由于allUnique()方法的for循环范围。
1 | public int lengthOfLongestSubstring(String s) { |
复杂度分析
时间复杂度:O(n^3),三重循环
空间复杂度:O(min(n, m))O(min(n,m)),我们需要 O(k)的空间来检查子字符串中是否有重复字符,其中 k 表示 Set 的大小。而 Set 的大小取决于字符串 n 的大小以及字符集/字母 m 的大小。
解法二:双指针+滑动串口
该题的实现思路主要是基于:滑动窗口。
什么是滑动窗口?
其实就是一个队列,比如例题中的 abcabcbb,进入这个队列(窗口)为 abc 满足题目要求,当再进入 a,队列变成了 abca,这时候不满足要求。所以,我们要移动这个队列!
如何移动?
我们只要把队列的左边的元素移出就行了,直到满足题目要求!如左出右进变为bca
一直维持这样的队列,找出队列出现最长的长度时候,求出解!
- 哈希法的实现可以基于Map定义key为字符串的中的每个字符,value为该字符的位置i+1(方便计算长度)
- 通过数组实现,应为字符串由字母组成所以可以根据ASCII码的字符大小128,存放字符的位置i+1。
这里推荐使用数组,数组的存取都是O(1)的实现,当然Map在此种情况下也是的。代码如下
1 | public int lengthOfLongestSubstring(String s) { |
复杂度分析
时间复杂度:O(n),只进行一次遍历
空间复杂度:O(m),m 是字符集的大小128
两种解法,充分体现了以空间换时间思想的,来一次加快算法处理速度。所以在算法题中哈希表数组和Map的代码也需要背诵记忆,才能游刃有余。
同类题相关
992. K 个不同整数的子数组
若你反复AC,且充分理解了本题解法,可以尝试去解答同类题992该题是困难题不过无妨,同类题的意思就是变形,往往是增加了特定的条件或者是针对不同的场景。所以同类题的目的是,透过现象看本质,一时的解不出不碍事,按我说的方法跟我学:LeetCode刷题大法,通过此种方法一定是越来越自信的刷题。
技巧与心得
- 开一个github仓库用来记录各种题解
- 在idea或者vscode中都提供了leecode的插件刷题,方便调试断走流程
- 遇到不会的题不要慌,稳住心态直接看题解
- 文字类的表述不如视图类的直观,图文并茂精选图解优先或者参考leetcode国际站的大牛题解
- 图解依旧看着吃力也无妨,可以在哔哩哔哩或者YouTube上,通过leecode + 题号,搜索高收视率的视频观看
- 多看几次本文跟我学:跟我学:LeetCode刷题大法,相信我你肯定能越刷越自信
最后的最后
看到最后,我相信你对本题应该有不一样的感受了吧!在此若有不对之处或建议等,留言告诉我;若有疑惑或者不一样的看法,也请告诉我,我们可以一起探讨学习!
我是Yangcy,该吃吃该喝喝,该学还得学,我们一起加油!