给定一个字符串,找出不含有重复字符的最长子串的长度。
示例 1:
输入: "abcabcbb" 输出: 3 解释: 无重复字符的最长子串是 "abc",其长度为 3。
示例 2:
输入: "bbbbb" 输出: 1 解释: 无重复字符的最长子串是 "b",其长度为 1。
示例 3:
输入: "pwwkew" 输出: 3 解释: 无重复字符的最长子串是 "wke",其长度为 3。 请注意,答案必须是一个子串,"pwke"是一个子序列 而不是子串。
思路分析:
这道题的难点在于怎么确定无重复字符的最长子串。因为可以存在这样的情况,子串和子串之间可能有交集,所以当我们从这个字符串的第一个字符开始遍历时,发现第一个重复的字符时,我们就需要记录当前的长度与之前的最大长度比较,取最大的那个作为目前子串的最大长度,然后我们就需要去寻找之前与这个字符相同的元素的索引位置,从这个位置的后一个位置的元素重新开始统计。这时,我们可以借助java中集合容器ArrayList来帮助我们进行统计。
具体实现方案:
先将字符串的第一个字符加入到容器中,然后从这个字符串的第二个字符开始,通过ArrayList容器的contains方法来判断容器是否包含这个元素,若不包含,则将这个元素添加到容器中,否则判断当前容器的大小与之前的最大长度max,取较大的那个更新为当前的最大长度。之后从这个元素的前一个元素开始,去寻找那个与当前这个元素相同的元素,并记录其索引位置,然后从这个索引位置的后一个位置开始,重新统计最长的无重复字符的子串的长度。当遍历完成后,再次判断容器的大小与当前的最大长度max,取最大的那个进行返回结果即可。
代码实现:
public static int lengthOfLongestSubstring(String s) {
if (s == null || s.length() == 0) { // 若字符串为空或长度为0
return 0;
}
char[] chs = s.toCharArray(); // 将字符串转化为字符数组
List<Character> list = new ArrayList<Character>(); // 定义集合容器ArrayList
list.add(chs[0]); // 将第一个元素添加到容器中
int max = 1; // 初始化最长子串的长度为1
for (int i = 1; i < chs.length; i++) { // 从字符串的第二个字符开始
if (!list.contains(chs[i])) { // 若容器中不包含这个元素,则添加到容器中
list.add(chs[i]);
} else { // 若容器包含这个元素
if (list.size() > max) { // 若此时容器的大小大于max,则将它的长度赋值给max
max = list.size();
}
int back = i - 1; // 从这个元素的前一个元素开始,向前去寻找与它相同的那个元素
while (back >= 0) {
if (chs[back] != chs[i]) {
back--;
} else {
break;
}
}
list.clear(); // 清空容器
list.add(chs[back + 1]); // 将寻找到的那个元素的后一个元素加入容器
i = back + 1; // 加上循环的i++,i=back+2,即从寻找到的那个元素的后两个元素开始重新统计
}
}
if (list.size() > max) { // 当上面循环完成,再次比较容器的大小与max
max = list.size();
}
return max;
}