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

LeetCode算法“无重复字符的最长子串”哈希表+滑动窗口+贪心

要解决 “最长无重复字符子串” 问题,我们可以通过滑动窗口算法结合哈希表高效求解。以下是详细的解题步骤,包括问题分析、算法设计、具体实现和边界处理:

一、问题分析

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

  • 输入 s = "abcabcbb",输出 3(最长子串为 "abc""bca" 等,长度均为 3)。
  • 输入 s = "bbbbb",输出 1(唯一无重复子串为单个 "b")。
  • 输入 s = "",输出 0(空字符串无有效子串)。

二、核心算法:滑动窗口 + 哈希表

1. 滑动窗口的基本思想

滑动窗口是一种通过双指针(左指针 left 和右指针 right)界定 “当前子串范围” 的技术。两个指针之间的区域称为 “窗口”,通过移动指针动态调整窗口大小,以寻找满足条件(无重复字符)的最长子串。

  • 右指针 right:负责 “扩展窗口”,不断向右移动以纳入新字符,尝试扩大子串长度。
  • 左指针 left:负责 “收缩窗口”,当右指针遇到重复字符时,左指针向右移动,直到窗口内不再包含重复字符,保证窗口的有效性。
2. 哈希表的作用

为了快速判断 “右指针新纳入的字符是否已在当前窗口中”,我们使用哈希表(本题中用大小为 128 的数组,对应 ASCII 字符集)记录字符在窗口中的存在状态:

  • 数组索引 = 字符的 ASCII 值(如 'a' 的 ASCII 值为 97,对应索引 97)。
  • 数组值 = 1 表示字符 “在当前窗口中”,0 表示 “不在窗口中”。
  • 优势:判断字符是否重复的时间复杂度为 O(1),比遍历子串检查(O (n))高效得多。

三、详细解题步骤

以示例 s = "abcabcbb" 为例,逐步演示算法执行过程:

步骤 1:初始化
  • 左指针 left 和右指针 right 均指向字符串起始位置(left = right = 0,对应字符 'a')。
  • 哈希表 hash[128] 初始化全为 0(表示所有字符初始状态为 “不在窗口中”)。
  • 变量 max_len 记录最长子串长度,初始为 0。
步骤 2:扩展右指针,纳入新字符

循环执行以下操作,直到 right 到达字符串末尾(*right == '\0'):

① 检查新字符是否重复

右指针当前指向的字符为 s[right],通过哈希表判断:

  • 若 hash[s[right]] == 0:字符未重复,可直接纳入窗口。
  • 若 hash[s[right]] == 1:字符已在窗口中,需先收缩左指针。
② 收缩左指针(若有重复)

当新字符重复时,左指针 left 向右移动,同时将移出窗口的字符从哈希表中移除(标记为 0),直到重复字符被移出窗口:

  • 例如,当 right 指向第 3 个字符 'a'(索引 3)时,哈希表中 hash['a'] = 1(因为 left 仍在索引 0,'a' 已在窗口中)。
  • 此时左指针右移(left = 1),并将 s[0] = 'a' 从哈希表中移除(hash['a'] = 0),窗口中不再有重复的 'a'
③ 纳入新字符并更新最长长度

将右指针指向的字符纳入窗口(hash[s[right]] = 1),计算当前窗口长度(right - left + 1),若大于 max_len 则更新 max_len

④ 右指针右移,继续扩展

重复上述步骤,直到 right 遍历完所有字符。

四、示例执行过程(s = "abcabcbb"

步骤right 指向字符是否重复左指针调整窗口范围当前长度max_len
10('a''a'[0,0]11
21('b''b'[0,1]22
32('c''c'[0,2]33
43('a''a'是(窗口有 'a')left→1[1,3]33
54('b''b'是(窗口有 'b')left→2[2,4]33
65('c''c'是(窗口有 'c')left→3[3,5]33
76('b''b'是(窗口有 'b')left→4[4,6]3→2(left→5 后)3
87('b''b'是(窗口有 'b')left→6[6,7]2→1(left→7 后)3

最终 max_len = 3,与预期结果一致。

五、代码实现(修正后)

int lengthOfLongestSubstring(char* s) {int hash[128]={0};int max = 0;char *left = s;char *right = s;  //左右指针初始位置均在S第一个字符while(*right!='\0'){while(hash[*right]) //直至重复元素对的前者被剔除{hash[*left]=0; //哈希表中删除左元素left++;}hash[*right] = 1;  //添加该右元素if(right-left+1>max)max = right-left+1;right++;   //右移}
return max;
}

六、关键细节与边界处理

  1. 空字符串:若 s 为空(*s == '\0'),循环不执行,直接返回 0,避免指针越界。
  2. 单字符字符串:如 s = "a",右指针处理 'a' 后,窗口长度为 1,max_len = 1
  3. 全重复字符:如 s = "aaaaa",每次右指针移动都会触发左指针收缩(始终与右指针相邻),窗口长度恒为 1,max_len = 1
  4. 字符类型转换:用 (unsigned char)*right 确保 ASCII 值为 0~255 的字符正确映射到数组索引(避免负数索引)。

七、时间与空间复杂度

  • 时间复杂度:O (n),其中 n 是字符串长度。每个字符最多被 left 和 right 各访问一次,总操作次数为 O (n)。
  • 空间复杂度:O (1),哈希表大小固定为 128(ASCII 字符集),与输入规模无关。

通过滑动窗口动态调整和哈希表快速判断,该算法高效解决了 “最长无重复字符子串” 问题,兼顾了时间和空间效率。

作者:牢笼

链接:https://leetcode.cn/problems/longest-substring-without-repeating-characters/solutions/3793743/cyu-yan-jie-jue-wu-zhong-fu-zi-fu-de-zui-yjcy/

来源:力扣(LeetCode)

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

http://www.dtcms.com/a/414218.html

相关文章:

  • 使用 TypeScript 实现基于 pgvector 的 LLM 自动化测试用例
  • LeetCode-hot100——验证二叉搜索树
  • CentOS7安装部署K8s
  • 【无标题】使用 Playwright 实现跨 Chromium、Firefox、WebKit 浏览器自动化操作
  • 做网站能用思源黑体吗国内外网站网站
  • 基于Qt的跨平台Word文档导出器WordEx的设计与实现
  • LeetCode 0812.最大三角形面积:三角形面积公式考察
  • LeetCode热题100--994. 腐烂的橘子--中等
  • 杭州做网站优化wordpress整站加密
  • 用Spark+Django打造食物营养数据可视化分析系统
  • 个人用云计算学习笔记 --17(DNS 服务器)
  • 泛微 Ecology10 OA 系统介绍
  • 哪个网站可以直接做ppt上海网站免费制作
  • STM32CubeMX安装教程
  • 游戏引擎以及游戏开发
  • 使用Python实现自动编写Word全自动化系统
  • 用flash做的经典网站微信公众号制作平台
  • OpenAI正式推出GPT-5-Codex增强型AI编程助手,该工具专为软件工程师设计
  • SpringMVC 进阶:核心组件详解与参数绑定全攻略
  • SpringMVC 实战:整合 MyBatis 实现完整 CRUD
  • Interleaving-Reasoning-Generation - 交错推理生成技术
  • 【C++】:继承全面解析
  • 大良营销网站建设机构设计专业所需网站
  • Spark专题-第二部分:Spark SQL 入门(8)-算子介绍-sort
  • 知识体系_分布式内存计算框架_spark
  • 银行 网站开发 干什么wordpress路径错误
  • QML 语法基础详解
  • ExcelVBA一键生成智能散点趋势图
  • ✨WPF编程基础【1.4】:类型转换器(含示例及源码)
  • 公链分析报告 - 模块化区块链2