【LeetCode】无重复字符串最长子串
题目描述
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
题目解析
这道题的目标是找出最长子串,并且该子串必须不包含重复字符,而且这个子串必须是原字符串中连续的一部分(见示例3中的解释说明)。
拿到题目时先不要心急想什么骚操作,我们先从最普通的操作开始把题目解出来,然后再来看如何优化。
接下来,我们画图分析一下,先随便弄一个长相普通的字符串:frankissohandsome,我们要从中找出我们想要的子串,那少不了需要遍历,我们设置两个变量from,to,分别存储寻找的目标子串在原字符串中的首尾位置。
首先,from和to的初始值都为0(String的序号从0开始),子串长度length = 1,最大子串长度maxLength = 1。

然后,我们将to的指向往后移动,并判断新遍历的字符是否已经存在于子串中,如果不存在,则将其加入子串中,并将length进行自增。

直到找到一个已存在于子串中的字符,或者to到达字符串的末尾。这里,我们找到了一个重复的s,序号为7,此时的子串为frankis,将此时的子串长度与最大子串长度相比较(目前为0),如果比最大子串长度大,则将最大子串长度设置为当前子串长度7。

接下来,我们继续寻找符合条件的子串,这里比较关键的一点是下一个子串的起始位置,这里我们将from直接跳到了序号为7的位置,因为包含ss的子串显然都不能满足要求。

然后我们依照之前的方法,找到第二个候选的子串sohand,长度为6,比目前的最大子串长度小,所以不是目标子串。

接着继续寻找,找到另一个候选子串ohands,长度小于最大子串长度,不是我们的目标子串。

继续寻找。

to到达了字符串末尾,找到另一个候选子串handsome,长度大于最大子串长度,这就是我们的目标子串。

于是我们的最大子串长度就轻松加愉快的找到了。接下来的事情就是把上面的思路转化成代码。
这里只需要注意一下from的跳转即可,每次跳转的序号为to指向的字符在子串中出现的位置 + 1。
常规解法
class Solution {
public int lengthOfLongestSubstring(String s) {
if (s == null || s.length() == 0) return 0;
int from = 0, to = 1, length = 1, maxLength = 1;
// to遍历直到字符串末尾
while (to < s.length()){
int site = s.substring(from, to).indexOf(s.charAt(to));
if (site != -1){
// to指向的字符已存在
length = to - from;
if (length > maxLength) maxLength = length;
// from 跳转到site+1的位置
from = from + site + 1;
}
to++;
}
// 处理最后一个子串
if (to - from > maxLength) {
maxLength = to - from;
}
return maxLength;
}
}
这里没有什么骚操作,考虑好边界情况就行了。有一个小细节需要注意,site代表的是子串中字符出现的位置,不是原字符串中的位置,因此from在跳转时,需要加上自身原来的序号。还有最后一个子串的处理不要忘记,因为当to遍历到字符串末尾时,会结束循环,最后一个子串将不会在循环内处理。
让我们提交一下:

击败了73%的用户,还不错。
常规解法优化
想想看,还有没有优化的空间呢?
那肯定是有的,首先我们想一想,当我们找到的最大子串长度已经比from所在位置到字符串末尾的位置还要长了,那就没有必要再继续下去了。
class Solution {
public int lengthOfLongestSubstring(String s) {
if (s == null || s.length() == 0) return 0;
int from = 0, to = 1, length = 1, maxLength = 0;
// to遍历直到字符串末尾
while (to < s.length()){
int site = s.substring(from, to).indexOf(s.charAt(to));
if (site != -1){
// to指向的字符已存在
length = to - from;
if (length > maxLength) {
maxLength = length;
}
// 判断是否需要继续遍历
if (maxLength > s.length() - from + 1) return maxLength;
from = from + site + 1;
}
to++;
}
// 处理最后一个子串
if (to - from > maxLength) {
maxLength = to - from;
}
return maxLength;
}
}
另外要处理类似bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb这样的字符串,上面的方法还是有很大优化空间的,我们可以用一个HashSet来存储所有元素,利用其特性进行去重,如果找到的子串长度已经等于HashSet中的元素个数了,那就不用再继续查找了。
class Solution {
public int lengthOfLongestSubstring(String s) {
if (s == null || s.length() == 0) return 0;
int from = 0, to = 1, length = 1, maxLength = 0;
Set<Character> set = new HashSet<>();
for (int i = 0; i < s.length(); i++){
set.add(s.charAt(i));
}
// to遍历直到字符串末尾
while (to < s.length()){
int site = s.substring(from, to).indexOf(s.charAt(to));
if (site != -1){
// to指向的字符已存在
length = to - from;
if (length > maxLength) {
maxLength = length;
}
if (maxLength > s.length() - from + 1) return maxLength;
if (maxLength >= set.size()) return maxLength;
from = from + site + 1;
}
to++;
}
// 处理最后一个子串
if (to - from > maxLength) {
maxLength = to - from;
}
return maxLength;
}
}
再提交一下:

哈哈哈哈,翻车了,所以这里引入一个HashSet用空间来换时间的方式不一定合适,看来测试用例里像bbbbbbbbbbbbbb这样的用例并不多啊。
那么今天的翻车就到此为止了,如果觉得对你有帮助的话记得点个关注哦。
【LeetCode】无重复字符串最长子串的更多相关文章
- Leetcode:003 无重复字符串
Leetcode:003 无重复字符串 关键点:给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度.示例 1:输入: "abcabcbb"输出: 3 解释: 因为无重复 ...
- LeetCode(3):无重复字符的最大子串
本内容是LeetCode第三道题目:无重复字符的最大子串 # -*- coding: utf-8 -*- """ Created on Sun Mar 10 20:14: ...
- [LeetCode]无重复字符的最长子串
给定一个字符串,找出不含有重复字符的最长子串的长度. 示例 1: 输入: "abcabcbb" 输出: 3 解释: 无重复字符的最长子串是 "abc",其长度为 ...
- python实现无重复字符串的最长子串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc&qu ...
- leetcode无重复字符的最长子串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc&qu ...
- 无重复字符串的最长子串 python
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc&qu ...
- LeetCode 无重复字符的最长子串(探索字节跳动)
题目描述 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "a ...
- LeetCode3.无重复字符的最大子串
给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: "abcabcbb"输出: 3 解释: 因为无重复字符的最长子串是 "abc&quo ...
- D - Milk Patterns (出现k次可重复的最长子串的长度)
题目链接:https://cn.vjudge.net/contest/283743#problem/D 题目大意:给你n个数,然后问你出现m次的最长子串的长度. 具体思路:和上一篇博客的内容差不多,这 ...
随机推荐
- Api 文档管理系统 RAP2 环境搭建
Api 文档管理系统 RAP2 环境搭建 发表于 2018-03-27 | 分类于 Api | 评论数: 4| 阅读次数: 4704 本文字数: 4.8k | 阅读时长 ≍ 9 分钟 RA ...
- 解决关于 ionic3 启动白屏 控制台错误提示:Uncaught SyntaxError Use of const in strict mode.
今天将项目从ionic2 升级为ionic3 ,ionic serve 运行在网页上无任何错误. 但是将项目打包成为android apk 却一直卡在启动页面 白屏,进不去的情况.后来在android ...
- No principal was found in the response from the CAS server
按网上的配置了 public String casServerUrlPrefix = "http://cas-server.com:8080/cas"; public String ...
- 【原创】关于Git暂存区的理解
关于Git暂存区的理解 暂存区可以说是Git的三大重要的区域之一,另外两个分别是工作目录和Git仓库,所以说对暂存区的深入理解可以帮助我们理解很多Git命令背后隐藏的工作原理.今天,本文将以 ...
- retry重试常见场景及实现
当我们的代码是有访问网络相关的操作时,比如http请求或者访问远程数据库,经常可能会发生一些错误,有些错误可能重新去发送请求就会成功,本文分析常见可能需要重试的场景,并最后给出python代码实现. ...
- Linux comm命令求出文件的交集、差集
A(1,2,3)和B(3,4,5),A和B的交集是3,A对B的差集是1和2,B对A的差集是4和5,A和B求差的结果是1.2.4.5. 在Linux中可以使用comm命令求出这些集. [root@xue ...
- 【转载】SpringBoot系列——Swagger2
微服务学习二:springboot与swagger2的集成:https://www.cnblogs.com/fengli9998/p/7522973.html 注:需要在启动类加 @EnableSwa ...
- 【golang-GUI开发】struct tags系统(一)
我们已经介绍了qt的signal和slot,现在该讲讲它的struct tags系统了.qt拥有多种的struct tags,我们会去一一了解它们. 什么是struct tags? struct ta ...
- [心得] 如何利用liquibase進行資料庫版本控制 - 基礎觀念
前言 - 會寫這篇除了是要記錄一下使用的過程之外,也是發現到網路上找來的教學幾乎都是跟其它環境做結合 比較沒有單純利用command進行的流程.也沒有整體觀念的介紹,所以將我所理解的整理分享給大家. ...
- 服务器文档下载zip格式
刚好这次项目中遇到了这个东西,就来弄一下,挺简单的,但是前台调用的时候弄错了,浪费了大半天的时间,本人也是菜鸟一枚.开始吧.(MVC的) @using Rattan.Core.Utility;@{ s ...