题目描述:

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

示例:

给定 "abcabcbb" ,没有重复字符的最长子串是 "abc" ,那么长度就是3。

给定 "bbbbb" ,最长的子串就是 "b" ,长度是1。

给定 "pwwkew" ,最长子串是 "wke" ,长度是3。请注意答案必须是一个子串,"pwke" 是 子序列  而不是子串。


 

解题过程:

方法一:暴力版本

显然,对于这道题我们可以像以往一样,遍历所有子串,对于这个方法,我相信大家都能想到,我就直接贴代码了。如下

//三个for暴力解决
   public static int lengthOfLongestSubstring(String s) {
       int max = 0;
       int temp = 0;
       char[] arr = new char[s.length()];
       for(int i = 0; i < s.length(); i++){
           arr[i] = s.charAt(i);
           temp = 1;
           for(int j = i + 1; j < s.length(); j++){
               int flag = 0;//用来判断s[j]是否在arr中
               for(int k = i; k < i + temp; k++){
                   if(arr[k] == s.charAt(j)){
                       flag = 1;
                       break;
                   }
               }
               if(flag == 1){ break;//重复
               } else {
                   arr[i+temp] = s.charAt(j);
                   temp++;
               }
           }
           if(temp > max){
               max = temp;
           }
       }
       return max;
   }

前面两个for循环用来遍历所有子串,第三个for循环用来判断字符s.charAt(j)是否在子串中。

方法二:各种优化

优化策略1:大家想一个问题,对于第三个循环,我们在数组里查找该数组是否拥有某个字符,这个查找的过程的时间复杂度是O(n),我们是否有其他什么方法把查找的过程的复杂度降低到O(1)?

前几次我们都有用过hashMap来进行映射,实际上这里一样可以用hashMap来保存子串,然后再判断s.charAt(j)是否子串中,这样我们就可以把查找过程的复杂度降低到O(1)了。

优化策略2:假如给你一个字符串:

"abcdca"

我们在遍历子串的过程中,最开始我们从第一个元素'a'开始遍历,当我们遍历到'abcd'时,在继续查找的时候遇到'c',此时"abcd"里面已经有'c'了,此时该子串查找完毕。此时长度为4,继续下一个子串的查找。

注意:我们继续下一个子串查找的时候,是从第二个元素'b'开始的。可是大家想一个问题,真的有必要从第二个元素'b'开始查找吗?,假如我们从'b'开始的时候,遍历到"bcd",继续遍历时又会再次遇到'c',此时长度为3。比上一个子串4的长度小。

实际上,我们是没有必要从第二个元素开始查找的。我们直接从'd'开始查找就可以了,也就是说,如果 s[j]s[j] 在 [i, j)[i,j) 范围内有与 j'j′ 重复的字符。我们再下一次寻找子串时,直接从j'+1的位置开始就行了。如果你不是很理解为啥会这样的话,可以找一些元素模拟一下勒。

优化策略3:我们每次在寻找子串的时候,会把子串放进hashMap里,假如我们要寻找下一个子串的话,理论上是需要把hashMap里面的元素给清空,然后再用来放置新的子串的。

但实际上,是不需要这样子的,hashMap里面的元素是可以重复利用的。先上代码吧,然后我在画图解释下优化策略三。如下:

//用hashMap映射
   public static int lengthOfLongestSubstring2(String s) {
       int max = 0;//保存最长子串的长度
       //用来记录子串是从哪个下标开始的
       int i = 0;
       Map<Character, Integer> map = new HashMap<>();        for(int j = 0; j < s.length(); j++){
           if(map.containsKey(s.charAt(j))){
               //从第一个重复元素的后一个开始
               i = Math.max(map.get(s.charAt(j))+ 1, i);
           }
           //j - i + 1 表示计算此时子串的长度
           max = Math.max(max, j - i + 1);
           map.put(s.charAt(j), j);
       }
       return max;
   }

假设字符串为"abcba",下面演示hashMap中元素的变化情况。

当j = 2。

当j = 3是,此时出现重复的字符(黄色的表示已经被代替的字符)。

当j = 4时。

j = 4时,hashMap有重复的字符a(下标为0的那个),为啥不会把i定位到下标为2的元素上?(因为它都已经遍历到从下标我为3的那里了,怎么可能还会倒回去)

这种方法的时间复杂度为O(n)。

从零打卡leetcode之day 4--无重复最长字符串的更多相关文章

  1. 从零打卡leetcode之day 2---两数相加

    前言 就是要把leetcode刷完,每天一道题,每天进步一点点. 从零打卡leetcode之day 2 题目描述: 给定两个非空链表来表示两个非负整数.位数按照逆序方式存储, 它们的每个节点只存储单个 ...

  2. 从零打卡leetcode之day 1--两数之和

    前言 就是要把leetcode的题刷完,每天一道题,每天进步一点点 从零打卡leetcode之day 1 题目描述: 给定一个整数数组和一个目标值,找出数组中和为目标值的两个数. 你可以假设每个输入只 ...

  3. Leetcode(3)无重复字符的最长子串

    Leetcode(3)无重复字符的最长子串 [题目表述]: 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 第一种方法:暴力 执行用时:996 ms: 内存消耗:12.9MB 效果: ...

  4. 【LeetCode题解】3_无重复字符的最长子串(Longest-Substring-Without-Repeating-Characters)

    目录 描述 解法一:暴力枚举法(Time Limit Exceeded) 思路 Java 实现 Python 实现 复杂度分析 解法二:滑动窗口(双指针) 思路 Java 实现 Python 实现 复 ...

  5. leetcode题解#3:无重复字符的最长子串

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

  6. Leetcode题库——3.无重复字符的最长子串

    @author: ZZQ @software: PyCharm @file: lengthOfLongestSubstring.py @time: 2018/9/18 20:35 要求:给定一个字符串 ...

  7. leetcode刷题3.无重复字符的最长子串

    题目:给定一个字符串,找出不含有重复字符的 最长子串 的长度. 示例: 给定 "abcabcbb" ,没有重复字符的最长子串是 "abc" ,那么长度就是3. ...

  8. LeetCode 第三题--无重复字符的最长子串

    1. 题目 2.题目分析与思路 3.思路 1. 题目 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3 ...

  9. Leetcode(3)-无重复字符的最长子串

    给定一个字符串,找出不含有重复字符的最长子串的长度. 示例: 给定 "abcabcbb" ,没有重复字符的最长子串是 "abc" ,那么长度就是3. 给定 &q ...

随机推荐

  1. 图论之Dijkstra算法

    Dijkstra算法是图论中经典的最短路径算法之一,主要用于解决单源最短路径问题. 单源最短路径问题,即求某个源节点到其他各个节点的最短路径. Dijkstra算法采用了贪心算法的思想,如图求1号节点 ...

  2. VB中StdPicture尺寸(Width,Height)转像素单位

    首先获得一个图片对象 Dim spic As StdPicture Set spic = LoadPicture("d:\0.bmp") '从文件获得 Set spic = Cli ...

  3. VB.NET或C#报错:You must hava a license to use this ActiveX control.

    VB.NET或者C# winform开发时,如果使用了Microsoft Visual Basic 6.0 ActiveX,并动态创建该控件实例,那么程序移植到没有安装Visual Basic 6.0 ...

  4. SSM框架mapper.xml模糊查询语句

    SSM框架mapper.xml模糊查询语句 在用SSM框架时,如果想要实现模糊查询,可以在mapper.xml文件中进行数据库语句的书写,方法有很多种,在这里我选择了两种介绍: 方法1: <se ...

  5. RDSS和RNSS

    RNSS英文全称Radio Navigation Satellite System,由用户接收卫星无线电导航信号,是一种卫星无线电导航业务,自主完成至少到4颗卫星的距离测量,进行用户位置,速度及航行参 ...

  6. window下如何使用文本编辑器(如记事本)创建、编译和执行Java程序

    window下如何使用文本编辑器(如记事本)创建Java源代码文件,并编译执行 第一步:在一个英文目录下创建一个 .text 文件 第二步:编写代码 第三步:保存文件 方法一:选择 文件>另存为 ...

  7. 配置maven和maven本地仓库

    l配置maven: 下载maven 网站: http://maven.apache.org/download.cgi 下载解压,在配置maven 右键本地电脑   选择 属性  在选择高级环境变量在选 ...

  8. Linux shell编程-退出的状态码

    linux 提供了一个专门的变量$?来保存上个已执行命令的状态码 linux 的错误状态退出状态码没有什么标准可遵循,但有一些参考 状态码 描述 0 命令成功结束 1 一般性未知错误 2 不适合的sh ...

  9. angular.js学习笔记(二)

    1.安装core ,shared模块 ng g m core  ng g m shared 2.在shared中导入core模块   core模块只加载一次所以将公共组件放到core中 3.创建公共组 ...

  10. ubuntu Pycharm 2017 3.3 Active

    1.打开激活窗口 2.选择 Activate new license with License server (用license server 激活) 3.在 License sever addres ...