可以先想下这两个问题:

1、怎样使用滑动窗口?

2、如何快速的解决字符查重问题?

滑动窗口

可以想象一下有两个指针,一个叫begin,一个叫now

这两个指针就指定了当前正在比较无重复的字符串,当再往后读取一个字符的时候,就需要比较该字符在begin到now之间是否有重复,如果有重复的话,则记录当前字符串长度,然后把begin往后移动,继续寻找后面的无重复字符子串。

例如,这里的字符串是:“fabcade”。

1、当开始比较字符串的时候,begin指向了第一个字符f,now也指向了第一个字符f,当前只有一个字符,也就不需要比较是否重复。

2、然后读取第二个字符,begin依然指向f,now指向了字符a,这个就需要比较一下a是否与之前的相同,没有相同的就继续读取。

3、当now指向第二个a的时候,begin指向f,此时发现前面已经有了一个a了,(这里可以先记录一下当前字符串长度)所以begin就需要往后移动到a后面的b的位置,则当前的字符串为:bca,之后继续读取d,等等等。

总而言之,滑动窗口记录了当前无重复的字符串,当遇到重复的时候,就把begin指针往后移动到不重复的位置(也就是前面那个重复字符的后面),然后继续遍历字符串到最后。

如何快速字符查重

因为这里都是字符,可以直接把该字符作为数组下标,当读取到一个字符的时候,直接把该字符下标对应的值置为1,表示当前已经存在一个字符(其实就是相当于把字符作为hash的key),例如:

  1. char array[127] = {0};
  2. char data = 'a';
  3. if (0 == array[data]) // 说明之前没有读到过该字符
  4. {
  5. array[data] = 1; // 置位,表示已经读到过该字符
  6. }
  7. else
  8. {
  9. // 说明此字符重复
  10. }

我们可以先想一下思路:

先初始化begin和now,然后循环读取字符串,每读取一个字符串,就在数组里查找一下,如果数组里不为0,就说明有重复的字符,需要把当前的字符串长度记录下来,然后begin往后移动到不重复的字符上,然后把该数组全部位置为0,再把begin后面的字符对应的数组置位1,最后再继续比较。

这么写当然也是可以,但不停的把数组置1再清0再置1,会很浪费时间,可以有其他方法吗?

当然是有的,我们可以这么写:

置位的时候,不填1,而填写当前字符所在的位置。

这样有什么好处呢?因为前面的begin,已经记录了当前字符串比较的起始位置,当读取到一个字符串:

如果他出现的位置在begin之前,就说明,虽然以前已经有了该字符,但那个是之前的事情了,不在现在的这个字符串范围之内,所以它还是不算重复的;

如果他上次出现的位置在begin之后,就说明在当前比较的字符串中已经有一个和他相同的字符了。

这样的话,通过位置信息就能够知道该字符在当前比较位置是否重复,就不需要反复的对数字进行清零和置位了。

在leetcode上,提高了9倍!(使用置位和清零花费44ms,使用位置标记花费4ms)


  1. int lengthOfLongestSubstring(char * s){
  2. int local[127] = {0}, data; // local数组就是用来记录每个字符出现的位置
  3. int lenNow = 0, lenMax = 0;
  4. int len = strlen(s);
  5. int begin = 1;
  6. for (int i=0; i<len; i++)
  7. {
  8. data = s[i];
  9. if ((0 == local[data]) || (begin > local[data]))
  10. {
  11. lenNow ++;
  12. }
  13. else
  14. {
  15. if (lenNow > lenMax) lenMax = lenNow;
  16. lenNow = i + 1 - local[data];
  17. begin = local[data] + 1; // 更新begin的位置
  18. }
  19. local[data] = i + 1;
  20. // 这里记录的位置是下标加1,也就是从1开始记录,为什么不从0开始记录呢?
  21. // 如果从0开始,那么0就有两种意思:该字符从没出现过,该字符出现的位置是0。当0正好又是begin的时候,比如字符串:"abca"
  22. }
  23. if (lenNow > lenMax) lenMax = lenNow;
  24. return lenMax;
  25. }

leetcode的Hot100系列--3. 无重复字符的最长子串--滑动窗口的更多相关文章

  1. [LeetCode]3. 无重复字符的最长子串(滑动窗口)

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

  2. LeetCode 第 3 题:无重复字符的最长子串(滑动窗口)

    LeetCode 第 3 题:无重复字符的最长子串 (滑动窗口) 方法:滑动窗口 滑动窗口模板问题:右指针先走,满足了一定条件以后,左指针向前走,直到不满足条件. 特点:左右指针的方向是一致的,并且是 ...

  3. leetcode刷题笔记-3. 无重复字符的最长子串(java实现)

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

  4. LeetCode随缘刷题之无重复字符的最长子串

    欢迎评论区交流. package leetcode.day_12_04; /** * 给定一个字符串 s ,请你找出其中不含有重复字符的最长子串的长度. * <p> * 示例1: * &l ...

  5. LeetCode(3):无重复字符的最长子串

    Medium! 题目描述: 给定一个字符串,找出不含有重复字符的 最长子串 的长度. 示例: 给定 "abcabcbb" ,没有重复字符的最长子串是 "abc" ...

  6. 【leetcode】 算法题3 无重复字符的最长子串

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

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

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

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

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

  9. Newtonsoft.Json C# Json序列化和反序列化工具的使用、类型方法大全 C# 算法题系列(二) 各位相加、整数反转、回文数、罗马数字转整数 C# 算法题系列(一) 两数之和、无重复字符的最长子串 DateTime Tips c#发送邮件,可发送多个附件 MVC图片上传详解

    Newtonsoft.Json C# Json序列化和反序列化工具的使用.类型方法大全   Newtonsoft.Json Newtonsoft.Json 是.Net平台操作Json的工具,他的介绍就 ...

随机推荐

  1. MQTT开源代理Mosquitto源码分析(访问控制篇)

    一.整体流程概览 从GitHub下载源码后,代理的源码在src中,同时还用到了lib库中的一些函数.对项目的工作流程有个大概理解是分析mosquitto的访问控制权限的基础,网络上已有很多中文博客在介 ...

  2. mysql的命令行安装,忘记密码,密码重置问题

    1.下载,安装msi 2.在MYSQL安装目录下,新建data目录 3.进入MYSQL的安装目录下,新建一个默认配置文件my.ini [mysql] # 设置mysql客户端默认字符集 default ...

  3. 毕设(三)NotifyIcon

    NotifyIcon是一个比较特殊的组件,其特殊之处是既可以把它归类到控件中,也可以把它归类到组件中.这是因为将其拖放到设计窗体后,我们并不能马上看到它的界面(像组件),而是在运行时才能看到它(像控件 ...

  4. MFC OnPaint()函数中最先调用CDialog::OnPaint()和最后调用CDialog::OnPaint()的巨大区别

    OnPaint()函数中最先调用CDialog::OnPaint()和最后调用CDialog::OnPaint()的巨大区别,如果没有注意这个问题就会出现无厘头式的绘图问题-- 效果就是出不来!在经过 ...

  5. VC 函数调用的 汇编代码 浅析

    摘要:主要谈谈vc里面函数调用汇编成汇编代码的情形,首先针对之前的一个小程序,说说vc编译器的优化. 例子程序: #include <iostream>using namespace st ...

  6. <iOS小技巧> 昵称格式判断

    一.使用方式 + 如下代码块功能:判断字体,判断字体输入格式       NSString *firstStr = [name substringToIndex:1];    NSArray *num ...

  7. 简单解说Linux命令输出与命令替换

    Linux命令能提高更方便的使用性能.下面就这就来讲术Linux命令.将一个程序或Linux命令的输出作为另一个程序或命令的输入,有两种方法,一种是通过一个临时文件将两个命令或程序结合在一起,例如上个 ...

  8. ansible(三)

    一.setup模块(收集信息 ) 1.ansible中的setup模块可以收集到的信息 ansible web -m setup ansible_all_ipv4_addresses # ipv4的所 ...

  9. 用java打印日历

    来自<java核心技术卷一> /** * Created by wangbin10 on 2019/1/3. * 打印当月日历 */ public class CalendarTest { ...

  10. 高并发 Nginx+Lua OpenResty系列(3)——模块指令

    Nginx Lua 模块指令 Nginx共11个处理阶段,而相应的处理阶段是可以做插入式处理,即可插拔式架构:另外指令可以在http.server.server if.location.locatio ...