Longest Substring Without Repeating Characters(leetCode)

本文介绍两种求解最长无重复子串的方法:第一种为简单遍历算法,通过逐字符扫描并记录最长无重复子串长度;第二种为优化算法,避免重复计算,提高效率。

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

解法一,最简单粗暴的方式

从字符串的第一个字符开始,遍历一遍,看以该字符开始的字符串里,最长的没有重复字符的子串的长度是多少,遍历一遍之后,最大的就是最后的解

public class LengthOfLongestSubstringWithoutRepeatingCharacters {

    public int lengthOfLongestSubstring(String s) {
        HashMap<String, Boolean> map = new HashMap<>(128);
        int result = 0;
        for (int i = 0; i < s.length(); i++) {
            int tmp = getCur(s, i, map);
            if (tmp > result) {
                result = tmp;
            }
        }
        return result;
    }

    private int getCur(String s, int startIndex, HashMap<String, Boolean> map) {
        int result = 0;
        for (int i = startIndex; i < s.length(); i++) {
            String curStr = s.substring(i, i + 1);
            if (map.get(curStr) != null && map.get(curStr)) {
                map.clear();
                return result;
            } else {
                result++;
                map.put(curStr, true);
            }
        }
        map.clear();
        return s.length() - startIndex;
    }

    @Test
    public void main() {
        System.out.println(lengthOfLongestSubstring(""));
//        System.out.println("111");
    }
}

解法二,对上述解法的优化
举个简单的例子,字符串abcdxcefgxyz,从a开始计算不重复的子串,当发现c重复的时候,下一轮还用从b开始吗?
不用,因为从b计算,到第二个c也是会重复的。
同样的道理,也不用从c开始计算。下一轮从d开始计算就可以了。
而且从d开始计算的时候,也不用完全从d开始,d是第一个,x是第二个,c是第三个这样,而是可以复用上一轮计算的结果,因为d,x,c这几个都已经比较过了,从d开始子串,长度起码已经是3了,下次只有从e开始比较就可以了。

        HashMap<String, Integer> map = new HashMap<>(128);
        int result = 0;
        int curLenth = 0;
        for (int i = 0, j = 0; i < s.length(); i++) {

            for (; j < s.length(); j++) {
                String curStr = s.substring(j, j + 1);
                if (map.get(curStr) != null) {

                    if (curLenth > result) { // 如果有重复字符,则记录一下当前值
                        result = curLenth;
                    }

                    for (int k = i; k < map.get(curStr); k++) {
                        map.remove(s.substring(k, k + 1));
                    }
                    i = map.get(curStr); // 下一次可以跳过中间的几次检查
                    curLenth = j - i; // 下一次检查时,curLenth可以而复用现在的一部分值
                    map.put(curStr, j);
                    j++;
                    break;
                } else {
                    curLenth++;
                    map.put(curStr, j);
                }
            }

            if (curLenth > result) {
                result = curLenth;
            }

        }
        return result;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值