题目描述
给定一个字符串 s
,请你找出其中不含有重复字符的最长子串 的长度。
方法一:滑动窗口(官方)
分析:
- 以
(a)bcabcbb
开始的最长字符串为(abc)abcbb
;
- 以
a(b)cabcbb
开始的最长字符串为a(bca)bcbb
;
- 以
ab(c)abcbb
开始的最长字符串为ab(cab)cbb
;
- ……
需要考虑的特殊情况有:
- 字符串为空的情况
- 字符串均为重复字符的情况
- 测试其他常规输入
算法:
我们使用两个指针表示字符串中的某个子串(或窗口)的左右边界,其中左指针代表着上文中「枚举子串的起始位置」,而右指针即为上文中的Rk
在每一步的操作中,我们会将左指针向右移动一格,表示我们开始枚举下一个字符作为起始位置,然后我们可以不断地向右移动右指针,但需要保证这两个指针对应的子串中没有重复的字符。在移动结束后,这个子串就对应着以左指针开始的,不包含重复字符的最长子串。我们记录下这个子串的长度;
在枚举结束后,我们找到的最长的子串的长度即为答案。
判断重复字符
在上面的流程中,还需要使用一种数据结构来判断是否有重复的字符,常用的数据结构是哈希集合。在左指针向右移动的时候,我们从哈希集合中移除一个字符,在右指针向右移动的时候,往哈希集合中添加一个字符
①官方代码(使用哈希保存字符)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| class Solution { public int lengthOfLongestSubstring(String s) { Set<Character> occ = new HashSet<Character>(); int n = s.length(); int rk = -1, ans = 0; for (int i = 0; i < n; ++i) { if (i != 0) { occ.remove(s.charAt(i - 1)); } while (rk + 1 < n && !occ.contains(s.charAt(rk + 1))) { occ.add(s.charAt(rk + 1)); ++rk; } ans = Math.max(ans, rk - i + 1); } return ans; } }
|
②我的代码(使用int数组保存状态)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| public class Question3 { public static void main(String[] args) { Question3 question3 = new Question3(); int maxLength = question3.lengthOfLongestSubstring("dvdf"); System.out.println(maxLength); } public int lengthOfLongestSubstring(String s) { if (s.equals("")) return 0;
int[] length = new int[s.length()]; for (int i = 0; i < length.length; i++) { length[i] = 1; } int maxLength = length[0]; char[] charArray = s.toCharArray(); for (int i = 1; i < charArray.length; i++) { int diffStringLength = getLastCommonCharBefore(s, charArray[i], i - length[i - 1], i); if (diffStringLength == length[i - 1]) { length[i] += length[i - 1]; maxLength = maxLength > length[i] ? maxLength : length[i]; } else { length[i] = diffStringLength + 1; maxLength = maxLength > length[i] ? maxLength : length[i]; } } return maxLength; }
public int getLastCommonCharBefore(String string, char targetChar, int startIndex, int endIndex) { String substring = string.substring(startIndex, endIndex); int index = substring.indexOf(targetChar); return substring.length() - 1 - index; } }
|
方法二:暴力求解
思路:遍历所有子串进行判断
评价:一般不用