当前位置: 首页 > news >正文

leetcode 面试经典 150 题:无重复字符的最长子串

链接无重复字符的最长子串
题序号3
类型字符串
解题方法滑动窗口
难度中等

题目

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

  • 示例 1:
    输入: s = “abcabcbb”
    输出: 3
    解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。

  • 示例 2:
    输入: s = “bbbbb”
    输出: 1
    解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。

  • 示例 3:
    输入: s = “pwwkew”
    输出: 3
    解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。

  • 提示
    0 <= s.length <= 5 * 104
    s 由英文字母、数字、符号和空格组成

解题

  1. 核心要点:这个问题可以通过滑动窗口的方法来解决。滑动窗口表示当前考虑的子串的范围,我们通过移动窗口的边界来找到不含有重复字符的最长子串。

    • 初始化:定义两个指针 left 和 right 分别表示窗口的左右边界,以及一个哈希表 char_index_map 来存储字符及其索引。
    • 扩展窗口:将 right 指针向右移动,扩展窗口,直到遇到重复的字符。
    • 更新最大长度:在每次移动 right 指针时,更新不含有重复字符的子串的最大长度。
    • 收缩窗口:当遇到重复的字符时,移动 left 指针,收缩窗口,直到重复的字符被移出窗口。
    • 重复步骤2-4:直到 right 指针到达字符串的末尾。
  2. 时间复杂度: O(n)

  3. 空间复杂度:O(n)

  4. c++ 实现算法

class Solution {
public:int lengthOfLongestSubstring(string s) {unordered_map<char, int> map; // 哈希表记录字符的最新索引,map 的键是字符,值是该字符的最后出现的索引位置int max_len = 0; // 最长子串长度int left = 0; // 滑动窗口的左边界for (int right = 0; right < s.size(); ++right) {// 如果当前字符在窗口内出现过,更新窗口的左边界//如果 map.find(s[right]) 返回的不是 map.end(),意味着哈希表中存在字符 s[right],//也就是说,字符 s[right] 在哈希表中出现过。//如果返回 map.end(),则说明哈希表中没有这个字符,即字符 s[right] 没有在哈希表中出现过。//map[s[right]] >= left,字符 s[right] 在窗口中的 上一次出现的位置 //大于等于当前窗口的左边界 left,那么就说明它是重复的。if (map.find(s[right]) != map.end() && map[s[right]] >= left) {//将 left 更新为字符 s[right] 最新出现位置的下一个位置left = map[s[right]] + 1;}// 更新当前字符的最新位置map[s[right]] = right;// 计算当前窗口的大小,更新最大长度max_len = max(max_len, right - left + 1);}return max_len;}
};
  1. 演示:以示例1为例

遍历字符串 s,right 从 0 到 7:

  1. right = 0,字符 ‘a’: map.find(s[right]) != map.end() 检查字符 ‘a’ 是否已经出现过。由于 map 为空,所以字符 ‘a’ 不在其中。 更新哈希表:map[‘a’] = 0。字符 ‘a’ 的最新索引是 0。计算当前窗口大小:right - left + 1 = 0 - 0 + 1 = 1。 更新 max_len:max_len = max(0,1) = 1。

  2. right = 1,字符 ‘b’: map.find(s[right]) != map.end() 检查字符 ‘b’ 是否已经出现过。字符 ‘b’ 不在哈希表中。 更新哈希表:map[‘b’] = 1。字符 ‘b’ 的最新索引是 1。计算当前窗口大小:right - left + 1 = 1 - 0 + 1 = 2。 更新 max_len:max_len = max(1, 2) = 2。

  3. right = 2,字符 ‘c’: map.find(s[right]) != map.end() 检查字符 ‘c’ 是否已经出现过。字符 ‘c’ 不在哈希表中。 更新哈希表:map[‘c’] = 2。字符 ‘c’ 的最新索引是 2。计算当前窗口大小:right - left + 1 = 2 - 0 + 1 = 3。 更新 max_len:max_len = max(2, 3) = 3。

  4. right = 3,字符 ‘a’: map.find(s[right]) != map.end() 检查字符 ‘a’ 是否已经出现过。字符 ‘a’ 已经在 map 中,且它的索引是 0(小于 right = 3)。 由于 ‘a’ 重复了,我们需要更新滑动窗口的左边界: left = map[‘a’] + 1 = 0 + 1 = 1,新的左边界是 1,即跳过 a 在左边的位置。 更新哈希表:map[‘a’] = 3。字符 ‘a’ 的最新索引是 3。 计算当前窗口大小:right - left + 1 = 3 - 1 + 1 = 3。 max_len 仍然是 3(不更新)。

  5. right = 4,字符 ‘b’: map.find(s[right]) != map.end() 检查字符 ‘b’ 是否已经出现过。字符 ‘b’ 已经在 map 中,且它的索引是 1(小于 right = 4)。 由于 ‘b’ 重复了,我们需要更新滑动窗口的左边界: left = map[‘b’] + 1 = 1 + 1 = 2,新的左边界是 2,即跳过 b 在左边的位置。 更新哈希表:map[‘b’] = 4。字符 ‘b’ 的最新索引是 4。 计算当前窗口大小:right - left + 1 = 4 - 2 + 1 = 3。 max_len 仍然是 3(不更新)。

  6. right = 5,字符 ‘c’: map.find(s[right]) != map.end() 检查字符 ‘c’ 是否已经出现过。字符 ‘c’ 已经在 map 中,且它的索引是 2(小于 right = 5)。 由于 ‘c’ 重复了,我们需要更新滑动窗口的左边界: left = map[‘c’] + 1 = 2 + 1 = 3,新的左边界是 3,即跳过 c 在左边的位置。 更新哈希表:map[‘c’] = 5。字符 ‘c’ 的最新索引是 5。 计算当前窗口大小:right - left + 1 = 5 - 3 + 1 = 3。 max_len 仍然是 3(不更新)。

  7. right = 6,字符 ‘b’: map.find(s[right]) != map.end() 检查字符 ‘b’ 是否已经出现过。字符 ‘b’ 已经在 map 中,且它的索引是 4(小于 right = 6)。 由于 ‘b’ 重复了,我们需要更新滑动窗口的左边界: left = map[‘b’] + 1 = 4 + 1 = 5,新的左边界是 5,即跳过 b在左边的位置。 更新哈希表:map[‘b’] = 6。字符 ‘b’ 的最新索引是 6。 计算当前窗口大小:right - left + 1 = 6 - 5 + 1 = 2。 max_len 仍然是 3(不更新)。

  8. right = 7,字符 ‘b’: map.find(s[right]) != map.end() 检查字符 ‘b’ 是否已经出现过。字符 ‘b’ 已经在 map 中,且它的索引是 6(小于 right = 7)。 由于 'b’重复了,我们需要更新滑动窗口的左边界: left = map[‘b’] + 1 = 6 + 1 = 7,新的左边界是 7,即跳过 b 在左边的位置。 更新哈希表:map[‘b’] = 7。字符 ‘b’ 的最新索引是 7。 计算当前窗口大小:right - left + 1 = 7 - 7 + 1 = 1。 max_len 仍然是 3(不更新)。

  1. c++ demo
#include <iostream>
#include <unordered_map>
#include <algorithm>
using namespace std;class Solution {
public:int lengthOfLongestSubstring(string s) {unordered_map<char, int> map; // 哈希表记录字符的最新索引,map 的键是字符,值是该字符的最后出现的索引位置int max_len = 0; // 最长子串长度int left = 0; // 滑动窗口的左边界for (int right = 0; right < s.size(); ++right) {// 如果当前字符在窗口内出现过,更新窗口的左边界//如果 map.find(s[right]) 返回的不是 map.end(),意味着哈希表中存在字符 s[right],//也就是说,字符 s[right] 在哈希表中出现过。//如果返回 map.end(),则说明哈希表中没有这个字符,即字符 s[right] 没有在哈希表中出现过。//map[s[right]] >= left,字符 s[right] 在窗口中的 上一次出现的位置 //大于等于当前窗口的左边界 left,那么就说明它是重复的。if (map.find(s[right]) != map.end() && map[s[right]] >= left) {//将 left 更新为字符 s[right] 最新出现位置的下一个位置left = map[s[right]] + 1;}// 更新当前字符的最新位置map[s[right]] = right;// 计算当前窗口的大小,更新最大长度max_len = max(max_len, right - left + 1);}return max_len;}
};int main() {Solution sol;string s = "abcabcbb";cout << "The length of the longest substring without repeating characters is: " << sol.lengthOfLongestSubstring(s) << endl;return 0;
}

相关文章:

leetcode 面试经典 150 题:无重复字符的最长子串

链接无重复字符的最长子串题序号3类型字符串解题方法滑动窗口难度中等 题目 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 示例 1: 输入: s “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”&#xff0c;所以其长度为 3。 …...

0101多级nginx代理websocket配置-nginx-web服务器

1. 前言 项目一些信息需要通过站内信主动推动给用户&#xff0c;使用websocket。web服务器选用nginx&#xff0c;但是域名是以前通过阿里云申请的&#xff0c;解析ip也是阿里云的服务器&#xff0c;甲方不希望更换域名。新的系统需要部署在内网服务器&#xff0c;简单拓扑图如…...

【前端】Jquery拍照,通过PHP将base64编码数据转换成PNG格式,并保存图像到本地

目录 一、需求 二、开发语言 三、效果 四、业务逻辑&#xff1a; 五、web端调用摄像头 六、示例代码 1、前端 2、后端 一、需求 web端使用jquery调用摄像头拍照&#xff0c;并使用PHP把base64编码转换成png格式图片&#xff0c;下载到本地。 由于js不能指定图片存储的…...

websocket再项目中的使用

WebSocket在项目中的使用‌主要包括以下几个方面&#xff1a; ‌WebSocket的基本概念和原理‌&#xff1a; ‌定义‌&#xff1a;WebSocket是一种基于TCP的协议&#xff0c;实现了浏览器与服务器之间的全双工通信。它通过HTTP/1.1协议的101状态码进行握手&#xff0c;建立连接‌…...

ajax同步执行async:false无效的解决方法

无效的情况&#xff1a; function ManHourCheck() {var StartDate $("#StartDate").val();//日报日期var EndDate $("#EndDate").val();//完成日期var UserID $("#UserID").val();//员工ID$.ajax({async: false,//加了这一行也没用!!!!!!!!!!…...

基于Qt的登陆界面设计

目标 自由发挥登录界面的应用场景&#xff0c;实现一个登录窗口的界面。 要求&#xff1a;每行代码都要有注释 代码 // 设置窗口大小为600x400像素 this->resize(600,400); // 设置窗口标题为"TheWitcher 巫师3&#xff1a;狂猎" this->setWindowTitle(&qu…...

HarmonyOS 输入框组件:TextInput 和 TextArea 深度解析

输入框组件是移动端开发中最常见的组件之一&#xff0c;常用于响应用户的输入操作&#xff0c;比如评论区的文本输入、聊天框的消息输入、表单内容填写等场景。在 HarmonyOS 中&#xff0c;TextInput 和 TextArea 分别用于单行和多行输入操作。除此之外&#xff0c;它们还可以与…...

【Golang】 Go 语言中的 Struct、JSON 和 Map 互转:详细指南

Go 语言中的 Struct、JSON 和 Map 互转:详细指南 在 Go 语言中,处理 JSON 数据、结构体类型和映射(map)是与 API、配置或数据库交互时非常常见的任务。理解如何在这些数据类型之间无缝转换对于高效的 Go 编程至关重要。以下是如何将 Go 结构体转换为 JSON、将 JSON 转换为…...

Azure Function流式返回

最近用azure function做了一个api和llm交互&#xff0c;需要流式返回。但是默认不支持流返回&#xff0c;搜索了一下。记录。 官方文档&#xff1a;https://techcommunity.microsoft.com/blog/azurecompute/azure-functions-support-for-http-streams-in-python-is-now-in-prev…...

智能座舱进阶-应用框架层-Jetpack主要组件

Jetpack的分类 1. DataBinding&#xff1a;以声明方式将可观察数据绑定到界面元素&#xff0c;通常和ViewModel配合使用。 2. Lifecycle&#xff1a;用于管理Activity和Fragment的生命周期&#xff0c;可帮助开发者生成更易于维护的轻量级代码。 3. LiveData: 在底层数据库更…...

GitLab分支管理策略和最佳实践

分支管理是 Git 和 GitLab 中非常重要的部分&#xff0c;合理的分支管理可以帮助团队更高效地协作和开发。以下是一些细化的分支管理策略和最佳实践&#xff1a; 1. 分支命名规范 • 主分支&#xff1a;通常命名为 main 或 master&#xff0c;用于存放稳定版本的代码。 • …...

【Unity】【VR开发】实现VR屏幕共享应用的几个重要插件和参考资料分享

【背景】 做了一个可以在局域网远程屏幕的VR应用&#xff0c;如果有相同兴趣的朋友也可以参考下我用的几个插件。 【使用或相关的关键插件】 piping server&#xff1a;这个是最基底的插件&#xff0c;基于它实现的信令通信。 https://github.com/nwtgck/piping-server/blob…...

数据结构---------二叉树前序遍历中序遍历后序遍历

以下是用C语言实现二叉树的前序遍历、中序遍历和后序遍历的代码示例&#xff0c;包括递归和非递归&#xff08;借助栈实现&#xff09;两种方式&#xff1a; 1. 二叉树节点结构体定义 #include <stdio.h> #include <stdlib.h>// 二叉树节点结构体 typedef struct…...

浏览器引入elasticsearch-head插件

elasticsearch-head插件下载&#xff1a; 链接: https://pan.baidu.com/s/1Dz3aU42HZCNg45iJoDOsMg?pwduvhg 提取码: uvhg 1、打开浏览器设置 2、选择拓展程序 3、选择elasticsearch-head插件下载 4、打开es-head插件 5、修改ip 6、登录...

【ELK】Filebeat采集Docker容器日志

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 介绍filebeat是如何工作的 使用部署filebeat 介绍 Filebeat 是一个用于转发和集中日志数据的轻量级传送器。 Filebeat 作为agent安装在服务器上&#xff0c;监视指…...

异步线程池与CountDownLatch

异步线程池 顾名思义&#xff0c;一个专门用来处理异步任务的线程池。可以避免线程的开销以及非阻塞的执行任务。 CountDownLatch 一个同步工具类&#xff0c;用于 让一个或多个线程等待一组操作完成。 业务场景 支付订单时&#xff0c;用户可以使用多张优惠劵&#xff0c…...

在图像上显示掩码、框和点的通用函数

在图像上显示掩码、框和点的通用函数 背景介绍函数实现与用途1. 显示掩码函数:`show_mask`2. 显示边界框函数:`show_box`3. 在图像上显示点函数:`show_points`4. 综合显示框和点函数:`show_points_and_boxes_on_image`5. 显示掩码并返回图像函数:`show_mask_on_image`6. 显…...

基于Matlab的变压器仿真模型建模方法(11):三相三绕组换流变压器的建模仿真

1.概述 换流变压器是直流输电系统中的关键设备,主要负责连接交流和直流系统,并实现电能的转换与传输。换流变压器在直流输电系统中的主要用途包括:传送电力:将电能从交流系统传输到直流系统或从直流系统传输到交流系统;电压变换:把交流系统电压变换到换流器所需的换相电压…...

代码随想录算法训练营day46|动态规划part12

今天就结束动态规划章节了&#xff0c;以后还要多加练习。 今天的两道题都很有难度&#xff0c;647回文子串的思路非常巧妙&#xff0c;因为用一维dp数组比较难表示子串的起点和终点&#xff0c;所以需要用二维dp数组表示&#xff0c;dp[i][j]表示以i为起点&#xff0c;j为终点…...

【C语言】头文件

所有学习过C语言的朋友都熟悉这样一段代码&#xff1a; #include <stdio.h>int main(int argc, char *argv[]) {return 0; }那么&#xff0c;你真的了解 <stdio.h> 吗&#xff1f; <stdio…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

React Native 导航系统实战(React Navigation)

导航系统实战&#xff08;React Navigation&#xff09; React Navigation 是 React Native 应用中最常用的导航库之一&#xff0c;它提供了多种导航模式&#xff0c;如堆栈导航&#xff08;Stack Navigator&#xff09;、标签导航&#xff08;Tab Navigator&#xff09;和抽屉…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

家政维修平台实战20:权限设计

目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系&#xff0c;主要是分成几个表&#xff0c;用户表我们是记录用户的基础信息&#xff0c;包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题&#xff0c;不同的角色&#xf…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

ffmpeg(四):滤镜命令

FFmpeg 的滤镜命令是用于音视频处理中的强大工具&#xff0c;可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下&#xff1a; ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜&#xff1a; ffmpeg…...