先上题:
给定一个字符串,找出不含有重复字符的最长子串的长度。
示例:
给定 "abcabcbb"
,没有重复字符的最长子串是 "abc"
,那么长度就是3。
给定 "bbbbb"
,最长的子串就是 "b"
,长度是1。
给定 "pwwkew"
,最长子串是 "wke"
,长度是3。请注意答案必须是一个子串,"pwke"
是 子序列 而不是子串。
问题的目标在于找寻最大的连续子字符串,所以可以把问题转换为找两个索引,分别为最大子字符串的头部索引和尾部索引。
针对每个字符在处理过程中的存储我们用哈希表来存储,主要是因为找寻字符有没有出现过的操作会变成O(1)的复杂度,可以提高算法时间性能。
在更新当前两个索引值的过程中主要会碰到两种情况:
- 当前位置的字符之前出现过了:去哈希表里面找这个字母最后出现过的位置,然后用这个位置的下一位置和当前的头部索引比较,取大的那个。然后更新这个字母最后出现的位置。
- 当前位置的字符没有出现过:根据当前的头部索引和尾部索引算个子字符串长度,和当前最优解比大小,保留大的那个,然后跳转到下个字符。
上代码:
import java.util.*; public class LengthOfLongestSubstring { public int lengthOfLongestSubstring(String s) { int result = 0, j = 0; if (s == null || s.length() == 0) return result; // 如果想直接获得之前处理过的数字或者字符的话,可以想想哈希表:) Map<Character, Integer> substring = new HashMap<Character, Integer>(); char[] chs = s.toCharArray(); for (int i = 0; i < chs.length; i ++) { if (substring.containsKey(chs[i])) j = Math.max(j, substring.get(chs[i]) + 1); substring.put(chs[i], i); result = Math.max(result, i - j + 1); } return result; } }2018/04/23 更新
应我家宝宝的要求,要我用动态规划去做这个题,本来以为这道题不能用动态规划做,但是做着做着发现还真的可以做,但是这个O(N^2)的时间复杂度有点高,LeetCode也没有AC,不知道有没有优化的好方法。
主要的思路就是创建一个二维布尔数组a去保存处理的过程值:
i表示子字符串头部的索引,j表示子字符串尾部的索引,里面存的布尔值表示这个以i为头部索引,以j为尾部索引的子字符串是不是不包含重复的字符,如果包含就置True,不包含则置False。
动态规划的状态转移公式如下所示:
a[i][j] = a[i + 1][j] && a[i][j - 1] && (s.charAt(i) != s.charAt(j))
举个例子:如果a[i][j]对应的子字符串为abb,那我判断这个字符串是否为真是通过检查ab和bb是否为真,可以看到ab是符合条件的字符串,但是bb并不符合,所以a[i][j]为false。当然,如果a[i + 1][j]和 a[i][j - 1]这两项都为真的话,说明除了头尾字符是否相同未知之外,其他字符都是和头尾字符不一样的,所以我们只要判断头尾字符是否相同即可。
接下来就是代码时间了,感觉可以进一步优化:
import java.util.*; public class LengthOfLongestSubstring { public int lengthOfLongestSubstringDP(String s) { int result = 0; if (s == null || s.length() == 0) return result; boolean[][] isSubstring = new boolean[s.length()][s.length()]; for (int i = isSubstring.length - 1; i >= 0; i --) { for (int j = i; j < isSubstring[0].length; j ++) { if (i == j || (isSubstring[i + 1][j] && isSubstring[i][j - 1] && s.charAt(i) != s.charAt(j))) { isSubstring[i][j] = true; result = Math.max(result, j - i + 1); } } } return result; } }