Loading

找到字符串的最长无重复字符子串 & 字符串的统计字符串

找到字符串的最长无重复字符子串

题目:找到字符串的最长无重复字符子串

《程序员代码面试指南》第94题 P300 难度:尉★★☆☆

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

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

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

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

计算完长度之后,pre位置和a位置哪一个在右边,就作为新的pre值。然后计算下一个位置的字符,整个过程中求得所有长度的最大值用len记录下来返回即可。
具体请参看如下代码中的maxUnique方法。

public int maxUnique(String str) {
    if (str == null || str.equals("")) {
        return 0;
    }
    char[] chas = str.toCharArray();
    int[] map = new int[256];
    for (int i = 0; i < 256; i++) {
        map[i] = -1;
    }
    int len = 0;
    int pre = -1;
    int cur = 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;
}

字符串的统计字符串

题目:字符串的统计字符串

《程序员代码面试指南》第80题 P258 难度:士★☆☆☆

这题没什么含金量,逐个遍历str[i]==str[i-1]num++否则拼接字符串。注意在遍历完成后还需要再拼接上最后一种字符的次数。不多说,直接看代码:

public String getCountString(String str) {
    if (str == null || str.equals("")) {
        return "";
    }
    char[] chs = str.toCharArray();
    String res = String.valueOf(chs[0]);
    int num = 1;
    for (int i = 1; i < chs.length; i++) {
        if (chs[i] != chs[i - 1]) {
            res = concat(res, String.valueOf(num), String.valueOf(chs[i]));
            num = 1;
        } else {
            num++;
        }
    }
    return concat(res, String.valueOf(num), "");
}

public String concat(String s1, String s2, String s3) {
    return s1 + "_" + s2 + (s3.equals("") ? s3 : "_" + s3);
}

(个人觉得用StringBuilder效率更高一点)

进阶问题

public char getCharAt(String cstr, int index) {
    if (cstr == null || cstr.equals("")) {
        return 0;
    }
    char[] chs = cstr.toCharArray();
    boolean stage = true;
    char cur = 0;
    int num = 0;
    int sum = 0;
    for (int i = 0; i != chs.length; i++) {
        if (chs[i] == '_') {
            stage = !stage;
        } else if (stage) {
            sum += num;
            if (sum > index) {
                return cur;
            }
            num = 0;
            cur = chs[i];
        } else {
            num = num * 10 + chs[i] - '0';
        }
    }
    return sum + num > index ? cur : 0;
}

书上的方法很繁琐,我的方法是通过split("_")分割字符串,分割后索引为奇数1、3、5…的字符串通过Integer.parseInt()转化后就是各个字符的次数,直接去统计就行,不需要像书上这样还挨个num=num*10+chs[i]去计算次数。。

posted @ 2022-04-16 12:09  幻梦翱翔  阅读(85)  评论(0)    收藏  举报