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

力扣 无重复字符的最长子串

滑动窗口,双指针移动找集合类的元素。

题目

无重复,可想到hashset集,然后由题找最长子串,说明要处理左右边界,可以用双指针,右指针一直遍历,左指针看到重复就加一,这像是一个滑动窗口。

class Solution {
    public int lengthOfLongestSubstring(String s) {
        //滑动窗口
        char[] ss = s.toCharArray();
        Set<Character> set = new HashSet<>();
        int res = 0;
        for(int left = 0, right = 0; right < s.length(); right++) {//右指针自增
            char ch = ss[right];//right指向的元素
            while(set.contains(ch)) {//set中有ch,则缩短左边界
                set.remove(ss[left]);//删除ch前面的元素
                left++;
            }
            set.add(ss[right]);//加入当前元素
            res = Math.max(res, right - left + 1);//当前不重复子串的长度
        }
        return res;
    }
}

但用while移除set的字符的循环显然是很影响效率的,因此改用map去记下每个字符的索引,直接进行跳转。虽然时间复杂度和空间复杂度一样,但会快一点。

时间复杂度O(n),空间复杂度O(n)。

class Solution {
    public int lengthOfLongestSubstring(String s) {
        HashMap<Character, Integer> map = new HashMap<>();
        int max = 0, start = 0;
        for (int end = 0; end < s.length(); end++) {
            char ch = s.charAt(end);//右边界循环遍历每个字符
            if (map.containsKey(ch)){
                //若被判断的字符上一次出现的位置就在滑动窗口内则需要改变左边界,进行+1。
                start = Math.max(map.get(ch)+1,start);
            }
            max = Math.max(max,end - start + 1);//找到最长子串
            //更新 s.charAt 的位置
            map.put(ch,end);
        }
        return max;
    }
    
}

还可以对空间复杂度进行优化,用双指针遍历,即不用存了,可以把空间复杂度到O(1)。双循环显然增加了时间复杂度,但时间复杂度O(N*∣Σ∣)。不重复子串区间长度不会超过字符集的长度∣Σ∣=128,当N足够大时,时间复杂度接近O(N)。使用set时cpu占用少,时间复杂度快一些,但显著提高了I/Os。不使用set,既减少了空间占用,又减少了I/Os,提高了运行速度。运行过后发现不用set更快。

class Solution {
  public int lengthOfLongestSubstring(String s) {
    int left = 0, length = 0, max = 0;
    for(int right=0; right < s.length(); right++){
        for(int k = left; k < right; k++){
            if(s.charAt(k) == s.charAt(right)){
                left = k+1;
                length = right-left;
                break;
            }
        }
        length++;
        if(max < length) max = length;
    }
    return max;
  }
}

以上均为优质题解的筛选,可多学一些思路。

滑动窗口要注意左右指针的遍历,然后结合常用集合类去存,在做算法题时要注意复杂度的优化。


http://www.kler.cn/a/536603.html

相关文章:

  • 2025蓝桥杯JAVA编程题练习Day3
  • 【C#】任务调度的实现原理与组件应用Quartz.Net
  • 软件系统性能测试的重要性和测试类型分享
  • Spring 框架及其主要模块
  • 使用 Redis Streams 实现高性能消息队列
  • web-文件上传-CTFHub
  • 已验证正常,Java输入字符串生成PDF文件
  • MySQL开窗函数种类和使用总结
  • 将仓库A分支同步到仓库B分支,并且同步commit提交
  • js中,正则表达式m修饰符说明
  • 数据完整性与约束的分类
  • 如何制定旅游计划:从零开始的旅行规划
  • 让相机自己决定拍哪儿!——NeRF 三维重建的主动探索之路
  • Repo vs Git:区别与优缺点
  • kafka服务端之延时操作前传--时间轮
  • docker 安装 mindoc
  • python小项目编程-初级(1、计算器)
  • 使用动态协议包,实现客户端与服务器端
  • 【探商宝】DeepSeek 最新模型对 ChatGPT 的影响及行业新变革
  • Java全栈项目:酒店客房管理系统
  • 【华为OD机考】2024E+D卷真题【完全原创题解 详细考点分类 不断更新题目 六种主流语言Py+Java+Cpp+C+Js+Go】
  • Java基础知识总结(四十八)--TCP传输、TCP客户端、TCP服务端
  • OnlyOffice 全面指南:从基础使用到深度自定义
  • postgreSQL16.6源码安装
  • unity学习29:摄像机camera相关skybox 和 Render Texture测试效果
  • IDEA启动项目慢问题处理