• 无重复字符的最长子串


    问题描述

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

    解法一:

      创建一个 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++;
        }
    }
  • 相关阅读:
    Java线程池使用说明
    Java并发编程:Thread类的使用
    深入理解Java的接口和抽象类
    编程中经常看到上下文context,这个上下文指得是什么?
    context
    setContentView和inflate区别
    Java for循环的几种用法分析
    Android学习06Android应用程序的基本组件
    learning java 重定向标准输入输出
    learning java 推回输入流
  • 原文地址:https://www.cnblogs.com/xiaofeng-fu/p/13933968.html
Copyright © 2020-2023  润新知