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

两道经典算法吃透双指针与滑动窗口!接雨水 + 无重复最长子串超详细题解

在算法面试与刷题中,双指针、滑动窗口是高频核心考点,既能解决数组区间问题,也能高效处理字符串匹配场景。本文将精讲两道力扣经典题:42. 接雨水(双指针预处理优化)、3. 无重复字符的最长子串(滑动窗口经典应用),从思路推导到代码实现,带你彻底吃透这类题型。


一、42. 接雨水

题目链接

42. 接雨水 - 力扣(LeetCode)

核心思路

每一列能接到的雨水量,由左侧最高柱子右侧最高柱子中较小的那个决定:

当前列雨水量 = min (左侧柱子最大高度,右侧柱子最大高度) - 当前柱子高度

如果直接对每个位置分别向左右遍历找最大值,会存在大量重复计算,时间复杂度极高。因此我们采用预处理数组优化

  1. 正向遍历,用数组maxLeft记录每个位置左侧最高柱子高度
  2. 反向遍历,用数组maxRight记录每个位置右侧最高柱子高度
  3. 最后遍历一次数组,累加每一列的接水量即可

递推公式

  • 从左到右:maxLeft[i] = max(height[i], maxLeft[i - 1])
  • 从右到左:maxRight[i] = max(height[i], maxRight[i + 1])

代码实现

class Solution { public int trap(int[] height) { int length = height.length; // 柱子数≤2无法接水 if (length <= 2) { return 0; } int[] maxLeft = new int[length]; int[] maxRight = new int[length]; // 预处理左侧最大高度数组 maxLeft[0] = height[0]; for (int i = 1; i < length; i++) { maxLeft[i] = Math.max(height[i], maxLeft[i - 1]); } // 预处理右侧最大高度数组 maxRight[length - 1] = height[length - 1]; for (int j = length - 2; j >= 0; j--) { maxRight[j] = Math.max(height[j], maxRight[j + 1]); } // 计算总接水量 int sum = 0; for (int i = 0; i < length; i++) { int count = Math.min(maxLeft[i], maxRight[i]) - height[i]; sum += count; } return sum; } }

二、3. 无重复字符的最长子串

题目链接

3. 无重复字符的最长子串 - 力扣(LeetCode)

核心思路

本题是滑动窗口的典型例题:把窗口看作字符串中一段无重复字符的区间[left, right]

  1. right指针向右扩展,尝试将新字符加入窗口
  2. 若当前字符已在窗口内重复,将left右移,收缩窗口直至无重复
  3. 每次窗口合法时,更新最长子串长度

使用哈希表记录字符最近一次出现的索引,可快速判断重复并定位窗口左边界。

代码实现

class Solution { public int lengthOfLongestSubstring(String s) { // 记录字符及其最近一次出现的下标 HashMap<Character, Integer> map = new HashMap<>(); int left = 0; int maxLength = 0; for (int right = 0; right < s.length(); right++) { char c = s.charAt(right); // 字符重复且在当前窗口内,移动左边界 if (map.containsKey(c) && map.get(c) >= left) { left = map.get(c) + 1; } // 更新当前字符最新位置 map.put(c, right); // 更新最大长度 maxLength = Math.max(maxLength, right - left + 1); } return maxLength; } }

总结

  1. 接雨水:通过预处理左右最大高度,避免重复遍历,以空间换时间,高效计算总雨水量
  2. 无重复最长子串:滑动窗口 + 哈希表快速去重,线性时间复杂度解决字符串区间问题
http://www.jsqmd.com/news/573278/

相关文章:

  • 避坑指南:在Ubuntu 22.04 LTS上用Quectel官方工具驱动RM520N-GL模块,为什么你的5G网卡起不来?
  • 3步打造企业级人脸检测系统:基于YOLOv8 Face的全流程实践指南
  • Omni-Vision Sanctuary 代码理解能力展示:解析可视化图表背后的数据与逻辑
  • ESP32-S3蓝牙配网避坑指南:常见问题及解决方案
  • FreeRTOS与RT-Thread嵌入式RTOS对比与选型指南
  • LSLib终极指南:5步掌握《神界原罪》和《博德之门3》MOD制作全流程
  • 【限时解禁】Cuvil编译器v0.9.3内部架构设计图(含Python动态类型静态化映射表),仅开放72小时
  • 解决PyCharm Terminal无响应:Windows中文用户名引发的故障排查
  • OpCore-Simplify:智能自动化OpenCore EFI构建工具的技术解析与实践指南
  • 别再死磕理论了!用Matlab Simulink和Cadence搞定Sigma Delta ADC设计的实战避坑指南
  • PHP自定义函数、返回值+参数传值
  • SEO网站推广企业如何进行链接建设
  • 嵌入式C++轻量级生命体基类:面向OOP的零开销实体抽象
  • 拆解Meta Ray-Ban同款主控:高通AR1芯片如何让AI眼镜‘听懂’你的手势和眼神?
  • 画图工具推荐|5款免费好用的流程图+组织架构图绘制软件
  • 通义千问2.5-7B高效工具链:Jupyter Notebook集成实战
  • 别再让MCSDK电流环PI参数拖后腿了!手把手教你从电机参数到代码配置的完整调参流程
  • PhotoMOS光控继电器:从基础电路到高效控制方案解析
  • CH422G_Wire库:轻量级Arduino I²C IO扩展方案
  • 嵌入式编程规范:提升代码质量与团队协作效率
  • 告别重复造轮子:用快马AI一键生成无名小站高效开发模板
  • 循环队列在IPC消息处理中的高效实现与优化
  • 给嵌入式开发者的英飞凌HSM实战指南:从AUTOSAR集成到密钥安全存储
  • 2026届最火的十大降重复率平台实测分析
  • 【完整源码+数据集+部署教程】工地高空安全防护装备检测系统源码分享[一条龙教学YOLOV8标注好的数据集一键训练_70+全套改进创新点发刊_Web前端展示]
  • cv_unet_image-colorization与Java集成:SpringBoot服务化部署案例
  • 2026最权威的十大降AI率神器实际效果
  • 忍者像素绘卷微信小程序用户体验:RPG式成就系统设计实践
  • 告别命令行:5分钟掌握ffmpegGUI视频处理新方式
  • 3个高效步骤:个人数字阅读管理完全指南