LeetCode #3

本贴最后更新于 2062 天前,其中的信息可能已经时移世改

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

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

思路:

  1. 暴破,从位置 0 开始,把遇到的字符放到 Set 中,如果有重复则向前推进
  2. 空间换时间,记录各个字符的位置,在遇到重复字符时向前推进,但直接跳到已有的重复字符之后一个字符开始计算
  3. 思路 2 的实现上的优化,直接用 String.charAt()获取单个字符,不先把整个字符串转换成数组(因为 String 底层就是字符数组了)

1000 万个随机字符的字符串耗时:

  1. cost: 3489 ms
  2. cost: 312 ms
  3. cost: 305 ms
    思路 3 有较大概率略微快于思路 2,但都比思路 1 快 10 倍以上,理论上字符串越长差别越明显

代码:

package xyz.quxiao.play.lab.leetcode;

import com.google.common.base.Stopwatch;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.RandomStringUtils;

/**
 * 给定一个字符串,找到最长不含相同字符的字串长度 * * @author 作者 :quxiao 创建时间:2017/11/7 18:21
 */public class Problem3 {

  public static void main(String[] args) {
    String s = randomStr();
    Stopwatch sw = Stopwatch.createStarted();
    int r1 = lengthOfLongestSubstring(s);
    sw.stop();
    System.out.println(r1 + " cost: " + sw.elapsed(TimeUnit.MILLISECONDS) + " ms");
    sw.reset();

    sw.start();
    int r2 = lengthOfLongestSubstring2(s);
    sw.stop();
    System.out.println(r2 + " cost: " + sw.elapsed(TimeUnit.MILLISECONDS) + " ms");
    sw.reset();

    sw.start();
    int r3 = lengthOfLongestSubstring3(s);
    sw.stop();
    System.out.println(r3 + " cost: " + sw.elapsed(TimeUnit.MILLISECONDS) + " ms");
    sw.reset();

  }

  public static String randomStr() {
    int max = 10000000;
    return RandomStringUtils.randomAlphabetic(max);
  }

  // 思路1:暴破,从0开始遍历每个字符加到set中,如果成功了比较当前长度与max大小;否则推进
  public static int lengthOfLongestSubstring(String s) {
    if (s == null || s.length() == 0) {
      return 0;
    }

    int max = 0;
    char[] chars = s.toCharArray();
    int len = chars.length;
    int idx = 0;
    while (idx < len) {
      // 计算该idx的最长字串
  int start = idx;
      Set set = Sets.newHashSet();
      while (start < len && set.add(chars[start++])) {
      }
      if (set.size() > max) {
        max = set.size();
      }
      idx++;
    }

    return max;
  }

  // 思路2:空间换时间,记录各个字符的位置,在遇到重复字符时向前推进,但直接跳到已有的重复字符之后一个字符开始计算
  public static int lengthOfLongestSubstring2(String s) {
    if (s == null || s.length() == 0) {
      return 0;
    }

    int max = 0;
    char[] chars = s.toCharArray();
    int len = chars.length;
    int i = 0;
    // 已经清除的最后一个idx,初始时-1表示未清除任何字符
  int lastClearIdx = -1;

    Map cMap = new HashMap<>();

    while (i < len) {
      char c = chars[i];
      // 不存在
  if (!cMap.containsKey(c)) {
        cMap.put(c, i);
        max = Math.max(max, cMap.size());
        i++;
      } else {
        int exist = cMap.get(c);
        // 清除 cur - exist之间的字符串
  for (int j = lastClearIdx + 1; j <= exist; j++) {
          cMap.remove(chars[j]);
        }
        lastClearIdx = exist;
      }
    }
    return max;
  }

  // 思路3,但是直接利用string.charAt(),不转换成arr
  public static int lengthOfLongestSubstring3(String s) {
    if (s == null || s.length() == 0) {
      return 0;
    }

    int max = 0;
    int len = s.length();
    int i = 0;
    // 已经清除的最后一个idx,初始时-1表示未清除任何字符
  int lastClearIdx = -1;

    Map cMap = new HashMap<>();

    while (i < len) {
      char c = s.charAt(i);
      // 不存在
  if (!cMap.containsKey(c)) {
        cMap.put(c, i);
        max = Math.max(max, cMap.size());
        i++;
      } else {
        int exist = cMap.get(c);
        // 清除 cur - exist之间的字符串
  for (int j = lastClearIdx + 1; j <= exist; j++) {
          cMap.remove(s.charAt(j));
        }
        lastClearIdx = exist;
      }
    }
    return max;
  }
}
  • LeetCode

    LeetCode(力扣)是一个全球极客挚爱的高质量技术成长平台,想要学习和提升专业能力从这里开始,充足技术干货等你来啃,轻松拿下 Dream Offer!

    209 引用 • 72 回帖 • 2 关注
  • 算法
    388 引用 • 254 回帖 • 22 关注

相关帖子

回帖

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • sts
    2 引用 • 2 回帖 • 149 关注
  • 反馈

    Communication channel for makers and users.

    123 引用 • 906 回帖 • 193 关注
  • 智能合约

    智能合约(Smart contract)是一种旨在以信息化方式传播、验证或执行合同的计算机协议。智能合约允许在没有第三方的情况下进行可信交易,这些交易可追踪且不可逆转。智能合约概念于 1994 年由 Nick Szabo 首次提出。

    1 引用 • 11 回帖 • 6 关注
  • Kubernetes

    Kubernetes 是 Google 开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。

    108 引用 • 54 回帖
  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    18728 引用 • 69951 回帖
  • C++

    C++ 是在 C 语言的基础上开发的一种通用编程语言,应用广泛。C++ 支持多种编程范式,面向对象编程、泛型编程和过程化编程。

    106 引用 • 152 回帖
  • 音乐

    你听到信仰的声音了么?

    59 引用 • 509 回帖
  • Sym

    Sym 是一款用 Java 实现的现代化社区(论坛/BBS/社交网络/博客)系统平台。

    下一代的社区系统,为未来而构建

    523 引用 • 4581 回帖 • 690 关注
  • 新人

    让我们欢迎这对新人。哦,不好意思说错了,让我们欢迎这位新人!
    新手上路,请谨慎驾驶!

    51 引用 • 226 回帖 • 1 关注
  • 资讯

    资讯是用户因为及时地获得它并利用它而能够在相对短的时间内给自己带来价值的信息,资讯有时效性和地域性。

    53 引用 • 85 回帖
  • danl
    64 关注
  • 大数据

    大数据(big data)是指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。

    89 引用 • 113 回帖
  • CodeMirror
    1 引用 • 2 回帖 • 121 关注
  • Postman

    Postman 是一款简单好用的 HTTP API 调试工具。

    4 引用 • 3 回帖
  • 房星科技

    房星网,我们不和没有钱的程序员谈理想,我们要让程序员又有理想又有钱。我们有雄厚的房地产行业线下资源,遍布昆明全城的 100 家门店、四千地产经纪人是我们坚实的后盾。

    6 引用 • 141 回帖 • 561 关注
  • Wide

    Wide 是一款基于 Web 的 Go 语言 IDE。通过浏览器就可以进行 Go 开发,并有代码自动完成、查看表达式、编译反馈、Lint、实时结果输出等功能。

    欢迎访问我们运维的实例: https://wide.b3log.org

    30 引用 • 218 回帖 • 605 关注
  • Solidity

    Solidity 是一种智能合约高级语言,运行在 [以太坊] 虚拟机(EVM)之上。它的语法接近于 JavaScript,是一种面向对象的语言。

    3 引用 • 18 回帖 • 352 关注
  • Spark

    Spark 是 UC Berkeley AMP lab 所开源的类 Hadoop MapReduce 的通用并行框架。Spark 拥有 Hadoop MapReduce 所具有的优点;但不同于 MapReduce 的是 Job 中间输出结果可以保存在内存中,从而不再需要读写 HDFS,因此 Spark 能更好地适用于数据挖掘与机器学习等需要迭代的 MapReduce 的算法。

    74 引用 • 46 回帖 • 549 关注
  • Hadoop

    Hadoop 是由 Apache 基金会所开发的一个分布式系统基础架构。用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。

    82 引用 • 122 回帖 • 619 关注
  • SSL

    SSL(Secure Sockets Layer 安全套接层),及其继任者传输层安全(Transport Layer Security,TLS)是为网络通信提供安全及数据完整性的一种安全协议。TLS 与 SSL 在传输层对网络连接进行加密。

    69 引用 • 190 回帖 • 497 关注
  • B3log

    B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:SymSoloVditor思源笔记

    1083 引用 • 3461 回帖 • 285 关注
  • 笔记

    好记性不如烂笔头。

    304 引用 • 777 回帖
  • Angular

    AngularAngularJS 的新版本。

    26 引用 • 66 回帖 • 511 关注
  • 小说

    小说是以刻画人物形象为中心,通过完整的故事情节和环境描写来反映社会生活的文学体裁。

    28 引用 • 108 回帖 • 1 关注
  • 招聘

    哪里都缺人,哪里都不缺人。

    189 引用 • 1056 回帖
  • PostgreSQL

    PostgreSQL 是一款功能强大的企业级数据库系统,在 BSD 开源许可证下发布。

    22 引用 • 22 回帖
  • RYMCU

    RYMCU 致力于打造一个即严谨又活泼、专业又不失有趣,为数百万人服务的开源嵌入式知识学习交流平台。

    4 引用 • 6 回帖 • 41 关注