C#算法之无重复字符的最长子串

yizhihongxing

C#算法之无重复字符的最长子串

问题描述

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

示例 1:

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

示例 2:

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

解决思路

暴力法

对于每一个字符从它开始依次枚举所有可能的子串,检查每个子串是否含有重复字符。

复杂度分析:
- 时间复杂度:O(n^3),枚举所有子串需要 O(n^2),检查每个子串是否含有重复字符需 O(n)
- 空间复杂度:O(min(n,m)),n 是字符串长度,m 是字符集大小。

滑动窗口法

使用哈希表来判重,定义两个指针 ij 分别代表窗口的左右边界。从左边界开始,逐一向右尝试扩大窗口大小,每次判断右侧添加的字符是否已经在窗口内出现过,如果已经出现过则缩小窗口,即左边界右移,同时左侧字符从哈希表中移除。

复杂度分析:
- 时间复杂度:O(n),窗口大小从1向右依次遍历,每个字符最多被访问两次,一次是右边界扫描,一次是左边界扫描。
- 空间复杂度:O(min(n,m)),右边界不断向右扩张,因此只需要在哈希表中存储字符的最后出现位置即可,而由于最多有m个不同字符,因此空间复杂度为O(min(n,m))。

代码实现

暴力法代码

public int LengthOfLongestSubstring(string s) {
    int n = s.Length;
    int ans = 0;
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j <= n; j++) {
            if (AllUnique(s, i, j)) ans = Math.Max(ans, j - i);
        }
    }
    return ans;
}

private bool AllUnique(string s, int start, int end) {
    HashSet<char> set = new HashSet<char>();
    for (int i = start; i < end; i++) {
        char c = s[i];
        if (set.Contains(c)) return false;
        set.Add(c);
    }
    return true;
}

滑动窗口法代码

public int LengthOfLongestSubstring(string s) {
    int n = s.Length, ans = 0;
    Dictionary<char, int> dict = new Dictionary<char, int>();
    for (int i = 0, j = 0; j < n; j++) {
        if (dict.ContainsKey(s[j])) i = Math.Max(dict[s[j]], i);
        ans = Math.Max(ans, j - i + 1);
        dict[s[j]] = j + 1;
    }
    return ans;
}

示例说明

示例一

输入: "abcabcbb"
输出: 3

暴力法的思路:逐一枚举所有子串,检查每个子串是否含有重复字符。

  • 子串"a"没有重复字符。
  • 子串"ab"没有重复字符。
  • 子串"abc"没有重复字符。
  • 子串"abca"有重复字符"a",因此子串"abca"被排除。
  • 子串"b"没有重复字符。
  • 子串"bc"没有重复字符。
  • 子串"bca"有重复字符"c",因此子串"bca"被排除。
  • 子串"bcab"有重复字符"b",因此子串"bcab"被排除。
  • 子串"c"没有重复字符。
  • 子串"cb"有重复字符"b",因此子串"cb"被排除。
  • 子串"cbb"有重复字符"b",因此子串"cbb"被排除。
  • 子串"cbba"有重复字符"b"和"a",因此子串"cbba"被排除。

因此,无重复字符的最长子串是"abc",长度为3。

滑动窗口法的思路:定义两个指针ij分别代表窗口的左右边界,使用哈希表来判重。从左边界开始,逐一向右尝试扩大窗口大小,每次判断右侧添加的字符是否已经在窗口内出现过,如果已经出现过则缩小窗口,即左边界右移,同时左侧字符从哈希表中移除。

  • 首先,i=0,j=0已经覆盖了第一个字符"a"。
  • 向右移动右指针,j=1,发现字符"b"未曾出现,此时窗口大小为2。
  • 向右移动右指针,j=2,发现字符"c"未曾出现,此时窗口大小为3。
  • 向右移动右指针,j=3,发现字符"a"曾经在(i,j)范围内出现过,于是将左指针右移,此时i=1,窗口大小为2。
  • 向右移动右指针,j=4,发现字符"b"曾经在(i,j)范围内出现过,于是将左指针右移,此时i=2,窗口大小为2。
  • 向右移动右指针,j=5,发现字符"c"曾经在(i,j)范围内出现过,于是将左指针右移,此时i=3,窗口大小为2。
  • 向右移动右指针,j=6,发现字符"b"曾经在(i,j)范围内出现过,于是将左指针右移,此时i=4,窗口大小为2。

因此,无重复字符的最长子串是"abc",长度为3。

示例二

输入: "bbbbb"
输出: 1

暴力法的思路:逐一枚举所有子串,检查每个子串是否含有重复字符。

  • 子串"b"没有重复字符。
  • 子串"bb"有重复字符"b",因此子串"bb"被排除。
  • 子串"bbb"有重复字符"b",因此子串"bbb"被排除。
  • 子串"bbbb"有重复字符"b",因此子串"bbbb"被排除。

因此,无重复字符的最长子串是"b",长度为1。

滑动窗口法的思路:定义两个指针ij分别代表窗口的左右边界,使用哈希表来判重。从左边界开始,逐一向右尝试扩大窗口大小,每次判断右侧添加的字符是否已经在窗口内出现过,如果已经出现过则缩小窗口,即左边界右移,同时左侧字符从哈希表中移除。

  • 首先,i=0,j=0已经覆盖了第一个字符"b"。
  • 向右移动右指针,j=1,发现字符"b"曾经在(i,j)范围内出现过,于是将左指针右移,此时i=1,窗口大小为1。
  • 向右移动右指针,j=2,发现字符"b"曾经在(i,j)范围内出现过,于是将左指针右移,此时i=2,窗口大小为1。
  • 向右移动右指针,j=3,发现字符"b"曾经在(i,j)范围内出现过,于是将左指针右移,此时i=3,窗口大小为1。
  • 向右移动右指针,j=4,发现字符"b"曾经在(i,j)范围内出现过,于是将左指针右移,此时i=4,窗口大小为1。

因此,无重复字符的最长子串是"b",长度为1。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#算法之无重复字符的最长子串 - Python技术站

(0)
上一篇 2023年5月31日
下一篇 2023年5月31日

相关文章

  • SpringBoot学习之Json数据交互的方法

    下面是”SpringBoot学习之Json数据交互的方法”的详细攻略: 1. Json数据交互的概述 JSON(JavaScript Object Notation)是一种轻量级的数据交互格式,常用于前后端数据传输。SpringBoot可以很方便地支持Json数据的交互,实现前后端数据的无缝传输。 2. 配置Json数据交互 在SpringBoot中,配置J…

    Java 2023年5月26日
    00
  • java中的静态代码块、构造代码块、构造方法详解

    Java中的静态代码块、构造代码块、构造方法详解 在Java中,我们可以通过概念上三种不同类型的代码块来实现特定的代码块执行顺序和实现方式:静态代码块、构造代码块、构造方法。下面将针对这三种代码块进行详细讲解。 静态代码块 静态代码块是在类加载的时候自动执行的代码块,且只会执行一次。我们可以通过static {…}的方式定义静态代码块。静态代码块的主要作…

    Java 2023年5月23日
    00
  • Java 实战范例之线上新闻平台系统的实现

    Java 实战范例之线上新闻平台系统的实现 目录 概述 技术选型 系统架构 实现步骤 1. 创建数据库和表 2. 用户注册和登录功能的实现 3. 新闻分类和展示功能的实现 4. 新闻发布和编辑功能的实现 结语 概述 本篇文档是针对实现一个线上新闻平台系统的完整攻略。该系统包括用户注册和登录,新闻分类和展示,新闻发布和编辑等功能。 技术选型 本系统使用的技术包…

    Java 2023年5月19日
    00
  • Java语言面向对象编程思想之类与对象实例详解

    Java面向对象编程思想之类与对象实例详解 在Java中,所有的事物都是对象,对象都有其自身的特征和行为。因此,Java是一种面向对象的语言。在Java中,类和实例是很重要的概念,我们需要对其进行深入的学习和理解。 类和对象 类是一种模板或蓝图,可以用来创建对象。具有相同属性和行为的对象,可以归纳为同一个类。对象则是类的一个实例,可以根据类来创建多个对象。 …

    Java 2023年5月26日
    00
  • Java整合mybatis实现过滤数据

    接下来我将详细讲解“Java整合MyBatis实现过滤数据”的完整攻略,包括以下几个步骤: 配置MyBatis 首先需要在项目中配置MyBatis,具体可以参考该教程:MyBatis官方文档。在配置好MyBatis后,就可以进行下一步。 创建Mapper接口 在使用MyBatis的过程中,很多开发者喜欢使用Mapper接口进行数据库操作,所以我们需要创建一个…

    Java 2023年5月20日
    00
  • Spring框架实现AOP的两种方式详解

    Spring框架实现AOP的两种方式详解 Spring框架是JavaEE应用中最常用的框架之一,其中一个主要的特性就是支持AOP(面向切面编程)的实现。在Spring框架中,AOP有两种主要的实现方式:基于代理(Proxy-based)和基于AspectJ(AspectJ-based)。 基于代理的AOP实现方式 基于代理的AOP实现方式是Spring框架默…

    Java 2023年5月19日
    00
  • java实现简单的俄罗斯方块

    Java实现简单的俄罗斯方块攻略 1. 搭建环境 首先需要搭建 Java 开发环境,具体可以根据个人喜好选择合适的集成开发环境(IDE),例如 Eclipse、IntelliJ IDEA 等。 2. 准备资源 在实现俄罗斯方块的过程中需要用到一些图片素材,例如方块图案,这些资源可以从图片库中或者网络下载得到。 3. 实现游戏界面 使用 Java Swing …

    Java 2023年5月18日
    00
  • 浅谈hibernate之映射文件VS映射注解

    如何选择使用Hibernate的映射文件或映射注解?这是Hibernate初学者常常疑惑的问题。本文将深入浅出地介绍这个话题,帮助读者更好地掌握Hibernate的使用方法。 什么是映射文件? Hibernate的映射文件定义了Java类和数据库表之间的映射关系。映射文件只是一个XML格式的文件,用于Hibernate根据属性及其映射关系创建数据表和对象。H…

    Java 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部