题目描述

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例 2:

输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

示例 3:

输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

题目解析

这道题的目标是找出最长子串,并且该子串必须不包含重复字符,而且这个子串必须是原字符串中连续的一部分(见示例3中的解释说明)。

拿到题目时先不要心急想什么骚操作,我们先从最普通的操作开始把题目解出来,然后再来看如何优化。

接下来,我们画图分析一下,先随便弄一个长相普通的字符串:frankissohandsome,我们要从中找出我们想要的子串,那少不了需要遍历,我们设置两个变量fromto,分别存储寻找的目标子串在原字符串中的首尾位置。

首先,fromto的初始值都为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】无重复字符串最长子串的更多相关文章

  1. Leetcode:003 无重复字符串

    Leetcode:003 无重复字符串 关键点:给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度.示例 1:输入: "abcabcbb"输出: 3 解释: 因为无重复 ...

  2. LeetCode(3):无重复字符的最大子串

    本内容是LeetCode第三道题目:无重复字符的最大子串 # -*- coding: utf-8 -*- """ Created on Sun Mar 10 20:14: ...

  3. [LeetCode]无重复字符的最长子串

    给定一个字符串,找出不含有重复字符的最长子串的长度. 示例 1: 输入: "abcabcbb" 输出: 3 解释: 无重复字符的最长子串是 "abc",其长度为 ...

  4. python实现无重复字符串的最长子串

    给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc&qu ...

  5. leetcode无重复字符的最长子串

    给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc&qu ...

  6. 无重复字符串的最长子串 python

    给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc&qu ...

  7. LeetCode 无重复字符的最长子串(探索字节跳动)

    题目描述 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "a ...

  8. LeetCode3.无重复字符的最大子串

    给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: "abcabcbb"输出: 3 解释: 因为无重复字符的最长子串是 "abc&quo ...

  9. D - Milk Patterns (出现k次可重复的最长子串的长度)

    题目链接:https://cn.vjudge.net/contest/283743#problem/D 题目大意:给你n个数,然后问你出现m次的最长子串的长度. 具体思路:和上一篇博客的内容差不多,这 ...

随机推荐

  1. Api 文档管理系统 RAP2 环境搭建

    Api 文档管理系统 RAP2 环境搭建  发表于 2018-03-27 |  分类于 Api |  评论数: 4|  阅读次数: 4704  本文字数: 4.8k |  阅读时长 ≍ 9 分钟 RA ...

  2. 解决关于 ionic3 启动白屏 控制台错误提示:Uncaught SyntaxError Use of const in strict mode.

    今天将项目从ionic2 升级为ionic3 ,ionic serve 运行在网页上无任何错误. 但是将项目打包成为android apk 却一直卡在启动页面 白屏,进不去的情况.后来在android ...

  3. No principal was found in the response from the CAS server

    按网上的配置了 public String casServerUrlPrefix = "http://cas-server.com:8080/cas"; public String ...

  4. 【原创】关于Git暂存区的理解

    关于Git暂存区的理解      暂存区可以说是Git的三大重要的区域之一,另外两个分别是工作目录和Git仓库,所以说对暂存区的深入理解可以帮助我们理解很多Git命令背后隐藏的工作原理.今天,本文将以 ...

  5. retry重试常见场景及实现

    当我们的代码是有访问网络相关的操作时,比如http请求或者访问远程数据库,经常可能会发生一些错误,有些错误可能重新去发送请求就会成功,本文分析常见可能需要重试的场景,并最后给出python代码实现. ...

  6. 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 ...

  7. 【转载】SpringBoot系列——Swagger2

    微服务学习二:springboot与swagger2的集成:https://www.cnblogs.com/fengli9998/p/7522973.html 注:需要在启动类加 @EnableSwa ...

  8. 【golang-GUI开发】struct tags系统(一)

    我们已经介绍了qt的signal和slot,现在该讲讲它的struct tags系统了.qt拥有多种的struct tags,我们会去一一了解它们. 什么是struct tags? struct ta ...

  9. [心得] 如何利用liquibase進行資料庫版本控制 - 基礎觀念

    前言 - 會寫這篇除了是要記錄一下使用的過程之外,也是發現到網路上找來的教學幾乎都是跟其它環境做結合 比較沒有單純利用command進行的流程.也沒有整體觀念的介紹,所以將我所理解的整理分享給大家. ...

  10. 服务器文档下载zip格式

    刚好这次项目中遇到了这个东西,就来弄一下,挺简单的,但是前台调用的时候弄错了,浪费了大半天的时间,本人也是菜鸟一枚.开始吧.(MVC的) @using Rattan.Core.Utility;@{ s ...