《程序员代码面试指南》给定一个字符串 返回最长无重复子串的长度

题目:
给定一个字符串 str,返回 str 最长无重复子串的长度。
举例:
str = "abcd" 返回 4
str = "aabcb",最长无重复子串为"abc",返回3。



解答:
如果 str 长度为 N,字符编码范围是M,本题可以做到时间复杂度为O(N),额外空间复杂度为O(M)。

1.在遍历str之前,先申请几个变量。哈希表 map,key表示某个字符,value为这个字符第一次出现的位置。
整型变量pre,如果当前遍历到字符str[i],pre表示必须以str[i - 1]字符结尾的情况下,最长无重复子串
开始位置的前一个位置,初始时pre = -1。整型变量len,记录每一个字符结尾的情况下,最长无重复子串
长度的最大值,初始时,len = 0。从左到右遍历字符串str,假设现在遍历到str[i],接下来求必须以str[i]
结尾的情况下,最长无重复子串的长度。

2.map(str[i])的值表示之前遍历中最近一次出现str[i]的位置,假设在a位置。想要求以str[i]结尾的最长无
重复子串,a位置必然不能包含进来,因为str[a]等于str[i]。

3.根据pre的定义,pre + 1 表示必须以str[i - 1]字符结尾的情况下,最长无重复子串开始的位置,假设在
a位置,也就是说,以str[i -1 ]结尾的最长无重复子串是向左扩展到pre位置才停止的。

4.如果pre的位置在a的左边,因为str[a]的位置是不能包含进来的,而str[a+1...i-1]上是不重复的,所以
以str[i]结尾的最长无重复子串就是str[a+1...i]。如果pre的位置在a的右边,以str[i]结尾的最长无重复子串
是向左扩充到pre结束的。所以以str[i]结尾的最长无重复子串扩充到pre也会停止,而且str[pre+1... i-1]
上肯定不含有str[i],s所以以str[i]结尾的最长无重复子串就是str[pre+1...i]

5.计算完长度后,pre位置和a位置哪一个在右边哪一个就作为新的pre值。然后计算下一个pre的值。所有长度
的最大值用len记录。
 

public class Longestnonrepeatingsubstring {
    public static int maxUnique(String str){
        if(str == null || str == ""){
            return 0;
        }
        char[] chas = str.toCharArray();
        int[] map = new int[256];
        for(int i = 0; i < 256; i++){
            map[i] = -1;
        }
        int pre = -1;
        int cur = 0;
        int len = 0;
        for(int i = 0; i != chas.length; i++ ){
            pre = Math.max(pre, map[chas[i]]);
            cur = i - pre;
            len = Math.max(len, cur);
            map[chas[i]] = i;
        }
        return len;
    }

    public static void main(String[] args) {
        String str = new String("abcabcdebc");
        System.out.println(maxUnique(str));

    }
}

参考资料:《程序员面试代码指南》左程云 著

猜你喜欢

转载自blog.csdn.net/young_1004/article/details/82822120