题目描述

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

示例 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. MySQL数据库事务详解

    微信公众号[程序员江湖] 作者黄小斜,斜杠青年,某985硕士,阿里 Java 研发工程师,于 2018 年秋招拿到 BAT 头条.网易.滴滴等 8 个大厂 offer,目前致力于分享这几年的学习经验. ...

  2. 一个前端开发者换电脑的过程(git篇)

    一,安装git. 要安装git,首先得把它下载下来.去到git官网. 现在开始安装. 讲真,这些东西哪些要勾哪些不要勾我也不清楚,所以全部都按默认的来,一路next. 现在再打开vscode的终端,发 ...

  3. vue-11-路由嵌套-参数传递-路由高亮

    1, 新建vue-router 项目 vue init webpack vue-router-test 是否创建路由: 是 2, 添加路由列表页 在 component下创建 NavList 页面 & ...

  4. eclipse连接github,链接不上 cannot open git-upload-pack(git-receive-pack)

    2018年2月8日后禁止通过TLSv1.1协议连接https://github.com 和 https://api.github.com. 原文地址为https://githubengineering ...

  5. C#4并行计算

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  6. spring jdbcTemplate 事务,各种诡异,包你醍醐灌顶!

    前言 项目框架主要是spring,持久层框架没有用mybtis,用的是spring 的jdbc: 业务需求:给应用添加领域(一个领域包含多个应用,一个应用可能属于多个领域,一般而言一个应用只属于一个领 ...

  7. Angular2入门:TypeScript的接口

  8. Go语言学习笔记(五) [函数]

    日期:2014年7月29日   1.函数定义:func (p type) funcname(q int) (r,s int) {return 0,0 }     func: 保留字,用于定义一个函数 ...

  9. Python丢弃返回值

    函数多个返回值 python的函数支持返回多个值.返回多个值时,默认以tuple的方式返回. 例如,下面两个函数的定义是完全等价的. def f(): return 1,2 def f(): retu ...

  10. iOS高效裁剪图片圆角算法

    项目有个需求:裁剪图片,针对头像,下面是要求: 大家可以看到这张图片的圆角已经去除,下面说说我在项目利用了两种方式实现此裁剪以及查看技术文档发现更高效裁剪方式,下面一一讲解:看下来大约需要15-20分 ...