无重复字符的最长子串
问题描述
给定一个字符串,找出不含有重复字符的最长子串的长度。
解法一:
创建一个 pre 数组表示长度,从左到右遍历字符串数组。
public static int lengthOfLongestSubstringMethod(String s){ // 数组没有赋值的时,所有元素会初始化为 0 // 字符为下标时,会将 ASCII 码作为下标 int[] pre = new int[128]; int ans = 0; int left = 0; // i 表示当前处理的第 i 个字符 for (int i = 0; i < s.length(); i++) { // c 为依次取出的单个字符 char c = s.charAt(i); //如果 pre[c] 不等于 0 表示数组中该位置被修改过,也就代表前面有重复字符 if (pre[c]!=0 && pre[c] > left){ // 更新 ans 最大值 // i - left重复元素下标 - 上一次没重复的下标 ans = Math.max(ans,i-left); // left 是为求下一个子串长度做准备,因为要求出的是最长的子串长度 // 更新 left,上一次没重复的下标 left=pre[c]; } // 如果 pre[c] 为 0,或者 pre[c] <= t pre[c] = i + 1; } return Math.max(ans, s.length() - left); }
解法二:
定义一个Set去保存是否有重复字符。
public static int lengthOfLongestSubstringMethod1(String s) { Set<Character> set =new HashSet<>(); int left =0,right = 0,max=0; while (right<s.length()){ if (set.contains(s.charAt(right))){ //移除左端口的数据 set.remove(s.charAt(left)); //左窗口右移 left++; }else{ //添加数据并且窗口右移 set.add(s.charAt(right)); right++; //比较多次set里面保存数据最多的值 max=Math.max(max,set.size()); } } return max; }
总结:
滑动窗口算法复杂度是O ( n ) 比暴力解要高效很多。可以看到算法是维护一个窗口,最关键的点就是何时使右边界向右移动使得窗口扩张和何时使左边界向右移动使得窗口收缩。
算法大概逻辑如下:
//定义左右窗口 int left = 0, right = 0; while (right < s.size()) { // 增大窗口 window.add(s[right]); right++; while (window needs shrink) { // 缩小窗口 window.remove(s[left]); left++; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix