Algorithm:leetcode #3 Longest Substring Without Repeating Characters

题目

 

解答

题目看着不难,试了几遍,修改了一下,很快就写出以下代码

private int leetcode_3_lengthOfLongestSubstring(String s) {
        int res = 0;
        List<Character> characters = new ArrayList<>();
        for (int i =0;i<s.length();i++){
            char c = s.charAt(i);
            if (characters.size()>0){
                int len = characters.size();
                if (characters.contains(c)){
                    if (len > res){
                        res = len;
                    }
                    int index = characters.lastIndexOf(c);
                    characters = characters.subList(index+1,len);
                }
            }
            characters.add(c);
        }

        return res>characters.size()?res:characters.size();
}

几个测试例子都通过,一提交,发现 too young too simple,运行效率太低,需要优化算法

观摩了评论区的解答,特贴出来分享一下:

方法1:

private int leetcode_3_lengthOfLongestSubstring(String s) {
        int n = s.length();
        int ans = 0;
        int start = 0;
        Map<Character, Integer> map = new HashMap<>();
        //  i用来循环字符串s中的字符,start用来记录子串起始的位置。
        for (int end = 0; end < n; end++) {
            //  判断是否出现重复值
            if (map.containsKey(s.charAt(end))) {
                //  比较看看重复值的前者是否在start位置之后(下标大于start),在start之后的话,说明在当前的区间内,
                //  [start,end]中存在重复值,那就是end和之前的某个值(假设下标是A)重复了,这样的话[start,end]这个区
                //  间就不能用了,所以start就要变成A的下一个字符的下标map.get(s.charAt(end))。
                //  如果重复值的前者在start位置之前,那么就不影响[start,end]区间,所以不用把值赋值给start。
                start = Math.max(map.get(s.charAt(end)), start);
            }
            //  计算的子串长度,这里+1是为了加上end本身,比如start是0,end - start要比实际长度少1个,所以要+1。
            ans = Math.max(ans, end - start + 1);
            //  存放每个字符最后出现的位置的下一个字符的下标,用于上面start的赋值。
            map.put(s.charAt(end), end + 1);
        }
        return ans;
}

方法2:

public int lengthOfLongestSubstring(String s) {
        int maxLength = 0;
        
        if (s != null) {
            List<Character> list = new ArrayList<>(s.length());

            for (int i = 0; i < s.length(); i++) {
                Character character = s.charAt(i);
                while (list.contains(character)) {
                    list.remove(0);
                }
                list.add(character);
                maxLength = Math.max(maxLength, list.size());
            }
        }
            
        return maxLength;
    }

方法3:

public int lengthOfLongestSubstring(String s) {
        if (s == null || s.length() == 0) return 0;
        int currentStart = 0;
        int currentEnd = 0;
        int currentMax = 0;
        int[] alph = new int[255];
        while((s.length() - currentStart > currentMax) && currentEnd < s.length()) {
            int cN = (byte)(s.charAt(currentEnd));
            if ((alph[cN] == 0) || (alph[cN] != 0 && alph[cN] <= currentStart)) {
                currentMax = Math.max(currentMax, currentEnd - currentStart + 1);
                alph[cN] = currentEnd + 1;
                currentEnd++;
            } else {
                currentStart = alph[cN];
                alph[cN] = currentEnd + 1;
                currentEnd++;
            }
        }
        return currentMax;
    }

这个方法比较难理解,不过运行极快,打败了99.85%!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

KWMax

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

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

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

打赏作者

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

抵扣说明:

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

余额充值