每日一道算法面试题(3):leetcode3 无重复字符的最长子串

题目:给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。

示例1:

输入: "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例 2:

输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

示例 3:

输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是"wke",所以其长度为 3。
    请注意,你的答案必须是 子串 的长度,"pwke"是一个子序列,不是子串。

算法思路:

  1. 暴力法:逐个检查所有的子字符串,看它是否不含有重复的字符;算法复杂度0(n^2);
  2. 借助队列先进先出的属性:遍历字符串的同时判断当前字符是否包含在前面遍历的子字符串中,若存在则依次把队列中的字符串“出列”,直到与当前遍历到的字符相同的字符“出列”为止;若不存在则字符串长度加1,继续遍历。每次遍历的时候要比较记录的最大长度和每个子串的长度,取最大值赋值给最大长度;利用这种思路实现的算法效率不是很高,在leecode官网提交的算法代码执行时间是8ms;
  3. 滑动窗口:借助队列实现起来比较简单,但增加了创建队列和遍历队列的开销,可以借鉴队列的核心原理实现:只需要记录子串在父串中的索引位置,不借助队列,也不新建字符串,防止增加额外的开销。利用这种思路实现的算法效率比较高,在leecode官网提交的算法代码执行时间是3ms;

算法代码:暴力法的代码比较简单,就不写代码了,感兴趣的可以自己实现一下。

算法代码:根据算法思路2,写出的算法具体代码如下:

    public int lengthOfLongestSubstring(String s) {
        if (s == null || s.length() == 0) {
            return 0;
        }
        int max = 0;
        int curMax = 0;
        ArrayDeque queue = new ArrayDeque<>();
        for (int i = 0; i < s.length(); i ++) {
            char curChar = s.charAt(i);
            if (!queue.contains(s.charAt(i))) {
                queue.add(curChar);
                curMax ++;
            } else {
                if (curMax > max) {
                    max = curMax;
                }
                char c = queue.remove();
                curMax --;
                while (c != curChar) {
                    c = queue.remove();
                    curMax --;
                }
                queue.add(curChar);
                curMax ++;
            }
        }
        if (curMax > max) {
            max = curMax;
        }
        return max;
    }

算法代码:根据算法思路3,写出的算法具体代码如下:

    public int lengthOfLongestSubstring(String s) {
      int max = 0; // 最长子串的长度
        int curMax = 0; // 记录当前遍历的子串长度
        int index = 0; // 记录已遍历的重复元素的位置
        char curChar;
        boolean contain = false;
        for (int i = 0; i < s.length(); i ++) {
            curChar = s.charAt(i);
            int j;
            for (j = index; j < i; j ++) {
                if (s.charAt(j) == curChar) {
                    contain = true;
                    break;
                }
            }
            if (!contain) {
                curMax ++;
                if (curMax > max) {
                    max = curMax;
                }
            } else {
                curMax = i - j;
                index = j + 1;
                contain = false;
            }
        }
        return max;
    }

如果你有疑问或更好的算法思路,欢迎留言交流!!!

你可能感兴趣的:(算法题,编程学习,计算机技巧)