题目描述
给定一个字符串,找出不含有重复字符的最长子串的长度。
样例
输入: "abcabcbb"
输出: 3
解释: 无重复字符的最长子串是 "abc",其长度为 3。
输入: "bbbbb"
输出: 1
解释: 无重复字符的最长子串是 "b",其长度为 1。
输入: "pwwkew"
输出: 3
解释: 无重复字符的最长子串是 "wke",其长度为 3。 请注意,答案必须是一个子串,"pwke"是一个子序列 而不是子串。
思路分析
方法一:看到无重复值,则想到set遍历,声明两指针i,j,指针j用来遍历字符串,指针i用来指向当前无重复子字符串的首坐标,由于采用的是hashset,contain方法复杂度O(1),所以整体复杂度O(n)
方法二:hashmap,思路大体相同,不过更新i指针的方式,由remove变为i = Math.max(i, map.get(s.charAt(j))+1),复杂度同样是O(n)
方法三:上面两种方法复杂度都是O(n),原因在于采用了哈希,contain方法不用遍历,直接访问即可,联想到了数组也有随机访问元素的特性,构造一个容量256的数组,坐标为对应ascii码,值为相应位置,思路与hashmap一致
代码
java版本
方法一
public static int lengthOfLongestSubstring(String s) {
int i = 0;
int j = 0;
int max = 0;
Set<Character> set = new HashSet<Character>();
while (j < s.length()) {
if (!set.contains(s.charAt(j))) {
set.add(s.charAt(j++));
max = Math.max(max, set.size());
}
else {
set.remove(s.charAt(i++));
}
}
return max;
}
方法二
public static int lengthOfLongestSubstring(String s) {
if (s.length() == 0) {
return 0;
}
HashMap<Character, Integer> map = new HashMap<Character, Integer>();
int max = 0;
for (int j = 0, i = 0; j < s.length(); j++) {
if (map.containsKey(s.charAt(j))) {
i = Math.max(i, map.get(s.charAt(j))+1);
}
map.put(s.charAt(j), j);
max = Math.max(max, j-i+1);
}
return max;
}
方法三
public static int lengthOfLongestSubstring(String s) {
int c[] = new int[256];
Arrays.fill(c, -1);
int max = 0;
int i = -1;
for (int j = 0; j < s.length(); j++) {
i = Math.max(i, c[s.charAt(j)]);
c[s.charAt(j)] = j;
max = Math.max(max, j - i);
}
return max;
}
go版本
func maxInt(a, b int) int {
if a > b {
return a
}
return b
}
func lengthOfLongestSubstring(s string) int {
max, i := 0, -1
c := [256]int{}
for j, _ := range c {
c[j] = -1
}
for j := 0; j < len(s); j++ {
i = maxInt(i, c[s[j]])
c[s[j]] = j
max = maxInt(max, j-i)
}
return max
}