LeetCode 149 Longest Substring Without Repeating Characters

本文介绍了一种使用HashMap和桶排序思想解决寻找字符串中最长无重复子串的问题。通过维护一个滑动窗口并利用HashMap记录字符最后一次出现的位置,可以有效地避免重复字符,并更新最长子串长度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Given a string, find the length of the longest substring without repeating characters. For example, the longest substring without repeating letters for "abcabcbb" is "abc", which the length is 3. For "bbbbb" the longest substring is "b", with the length of 1.

分析:见到非重复,应该想到Hash。

这题可以用HashMap来存放字符和对应下标的关系,然后遍历,如果遇见重复的,就可以直接找到上一个重复字符的出现位置,把之前的全部清0.

怎么把之前的全部清除呢?

这里用一个start变量,记录当前字符串开始的位置,如果碰见重复的,则从start开始,从HashMap里移除现有值,直到重复的字符,就实现了对之前元素的清除。

public class Solution {
    public int lengthOfLongestSubstring(String s) {
        
        HashMap<Character, Integer> map = new HashMap<Character, Integer>();
        int max = 0;
        int start = 0;
        for(int i=0; i<s.length(); i++){
            char c = s.charAt(i);
            if(map.containsKey(c)){
                max = Math.max(max, map.size());
                for(int j=start; j<i; j++){
                    if(s.charAt(j) == c){
                        start = j+1;
                        break;
                    }
                    map.remove(s.charAt(j));
                }
            }else{
                map.put(c, i);
            }
        }
        return Math.max(max, map.size());
    }
}

下面解法,用的是桶排得思想,假设全部为ASCII字符,用一个长256的数组当字典,原理和Hash是一样的,局限是假定字符都是ASCII的。

public class Solution {
    public int lengthOfLongestSubstring(String s) {
        boolean[] flag = new boolean[256];
        
        int result=0;
        int j=0;
        char[] arr = s.toCharArray();
        
        for(int i=0; i<arr.length; i++){
            char c = arr[i];
            if(flag[c]){//如果为真,说明已经存过
                result = Math.max(result, i-j);
                for(int k=j; k<i; k++){
                    if(arr[k]==c){//找到c的下标,更新j
                        j=k+1;
                        break;
                    }
                    flag[arr[k]]=false;
                }
            }else
                flag[c]=true;
        }
        result = Math.max(arr.length-j,result);
        return result;
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值