力扣真题:无重复字符的最长子串(三种方法)

这道题我一开始使用了Set加类似滑动窗口的方法,最后解得出来,但效率不尽人意,最终用到是滑动窗口+指针+数组的方式讲效果达到最优,超过近99%的代码。

1、第一版

class Solution {
    public int lengthOfLongestSubstring(String s) {
        //先判断特殊情况
        if (s.equals("")){
            return 0;
        }
           //x[i]记录的是以下标为i字符为最后一个字符时不重复字符字串的长度
          Integer [] x = new Integer[s.length()];
        char[] chars = s.toCharArray();
        for (int i = 0; i < s.length(); i++) {
            int num = 0;
            //记录以下标为i字符为最后一个字符的字串。
            HashSet <Character> aa = new HashSet<>();
            for (int j = i; j >=0; j--) {
                aa.add(chars[j]);
                //当子串里有字符被去重了,就说明不能再往下了。
                if (aa.toArray().length!=++num){
                    num--;
                    break;
                }
            }
            x[i]=num;
        }
        int max = Integer.MIN_VALUE;
        for (int i = 0; i < x.length; i++) {
            if (max<x[i]){
                max = x[i];
            }
        }
        return max;
    }
}

2、第二版

使用了普通的滑动窗口的思路。

class Solution {
    public int lengthOfLongestSubstring(String s) {
        //维护者left和right指针中存在的字符
      HashSet<Character> hashSet = new HashSet<>();
        int left = 0;
        int right = 0;
        int max = 0;//最长长度
        while(right<s.length()){
             //如果此时right指向的字符已经在left和right指针中间了
               //就将left向右移,直至此时right指向的字符不存在于hashSet当中了
            if (hashSet.contains(s.charAt(right))){
                hashSet.remove(s.charAt(left++));
            //如果不存在于hashSet当中就继续right又移,并将其添加到集合当中
            //更新max;
            }else {
                hashSet.add(s.charAt(right++));
                max = Math.max(max,right-left);
            }
        }
        return max;
    }
}

3、第三版

此时不需要维护那个set字串了,直接维护一个数组,记录这上一次这个字符出现的下标,如果出现重复字符,直接将left跳转到这个上一次出现字符的后一个,直接一步到位,不需要其一步步向右移动了。

class Solution {
    public int lengthOfLongestSubstring(String s) {
    //维护一个数组,记录这上一次这个字符出现的下标
      int[] aaa = new int[128];
        for (int i = 0; i < aaa.length; i++) {
            aaa[i]=-1;
        }
        int max = 0;
        int left = 0;
        int right = 0;
        char[] chars = s.toCharArray();
        int length = s.length();
        while (right<length){
  //进行比较如果left指向的位置晚于这个字符上一次出现的位置,就说明此时窗口有两个这个字符了, 
//直接进行跳转,到上一次字符的后一个。
            left = Math.max(left,aaa[chars[right]]+1);
            //max重新赋值
            max = Math.max(right-left+1,max);
            aaa[chars[right]] = right;
    //窗口右移
            right++;
        }
        return max;
    }
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

日上三杆快起床

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值