theme: smartblue
一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第27天,点击查看活动详情。
无重复字符的最长子串
题目解析
题目素材解析
根据题目的描述来看,就只给了一个字符串s。
并且这个字符串可能很长,长度最小为0,最大为50000。
并且字符串中可能存在英文、数字、符号、空格等元素。
我的解读
题目的预期结果是要在一个字符串中找出一个最长子串的长度,并且保证这个子串中的字符不重复。
我对本题的思路,其实是有两种方法。
其一,就是暴力美学的做法,利用双重循环来获取结果。但是很不幸,这种方法在我本地执行没有问题,就是慢;但竟然在LeetCode中执行超时,简直欲哭无泪。
其二,也是没有别的办法,为了运行通过,只能尝试其他方法。发现大家都在用滑动窗口的方式。
所以我就理了理思路,大概有以下几个重点需要突破一下。
一,在子串拼接中如何判断是否存在过某字符,可以使用Set集合,不需要字符出现的顺序,只需要判断是否存在某个元素即可。
二,理解滑动窗口的概念,妥善使用索引值。
滑动窗口的图例(从Ikaruga这个大佬题解中拿的)
解题思路
有了大概的思路,解题也就没那么难了。
特殊情况单独处理一下即可。
第一步,先声明一个结果值result,Set集合(存放字符)。
第二步,声明一个起始位置l。
第三步,根据素材字符串的长度来循环遍历。
第四步,判断是否在Set集合中存在,如果不存在,则证明此窗口往右延伸。
第五步,如果存在,则需要窗口头部向尾部缩进,并且要缩进到当前值的下一个位置。
以此类推,得到最终结果。
这道题还是要先理解滑动窗口的概念,才能解出来。
代码
```java class Solution { /** * 滑动窗口 * 弃用split分隔方法,使用charAt方法提升效率。 * @param s * @return */ public int lengthOfLongestSubstring(String s) { //处理特殊情况 if(s.length() == 0){ return 0; } //声明一个结果值 int result = 0; //声明一个Set集合 Set set = new HashSet<>(); int l = 0; for (int r = 0; r < s.length(); r++) { Character si = s.charAt(r); if(set.contains(si)){ int z = l; while (true){ if(l < r && s.charAt(l++) == s.charAt(r)){ break; }else if(l >= r){ l = z; break; } } } if(r - l + 1 > result){ result = r - l + 1; } set.add(si); } return result; }
} ```
执行结果
一开始想多判断一下特殊情况,结果聪明反被聪明误,又提交错好几次。
Java代码本地执行
Java本地可调试代码,请参考github/Ijiran,可通过索引看到相应代码。
如下图所示: