题目要求:
给定一个字符串,请找出其中无重复字符的最长子字符串。
样例
例如,在"abcabcbb"
中,其无重复字符的最长子字符串是"abc"
,其长度为 3
。
对于,"bbbbb"
,其无重复字符的最长子字符串为"b"
,长度为1
。
O(n) 时间
原题地址:
LeetCode:https://leetcode.com/problems/longest-substring-without-repeating-characters/#/description
LintCode:http://www.lintcode.com/zh-cn/problem/longest-substring-without-repeating-characters/#
分析:
我第一次做这题的时候,是用一种最普通的做法——遍历两次,穷举所有的字符串,找出不重复字符串,存其长度。最后返回长度的最大值。
但是这样做的问题是时间复杂度为O(n^2),和题目要求不符,所以在LeetCode和Lintcode上的提交都扑街了。然后意识到应该采用HashMap,但一时也拿不出确切的方法,于是搜索了一下本题做法。
现在就在这篇博客贴一下两种做法吧:
做法一(时间复杂度O(n^2)):
public int lengthOfLongestSubstring(String s) {
String res = "";
int temp = 0;
ArrayList<Integer> list = new ArrayList<Integer>();
if (s == null || s.length() == 0) {
} else if (s.length() == 1) {
temp = 1;
} else {
int i = 0;
while (i < s.length() - 1) {
int j = 1;
while (j <= s.length() - i) {
if (isRepetitive(s.substring(i, i + j))) {
res = s.substring(i, i + j);
temp = Math.max(temp, res.length());
}else{
break;
}
j++;
}
i++;
}
}
return temp;
}
// 判断字符串是否有重复字符
public static boolean isRepetitive(String s) {
boolean b = true;
if (s.length() > 1) {
for (int i = 1; i < s.length(); i++) {
if (s.substring(0, i).contains(s.substring(i, i + 1))) {
b = false;
break;
}
}
}
return b;
}
做法二(时间复杂度为O(n)):
public int lengthOfLongestSubstring(String s) {
int temp = 0;
if (s == null || s.length() == 0) {
} else {
Map<Character, Integer> myMap = new HashMap<Character, Integer>();
// 用以保存不重复字符串的长度
int[] strlength = new int[s.length() + 1];
// 用字符数组表示字符串
char[] str = s.toCharArray();
for (int i = 0; i < str.length; i++) {
Integer lastPosOfChar = myMap.get(str[i]);
if (lastPosOfChar == null) {
// 更新最长无重复子串的长度
strlength[i] = i == 0 ? 1 : strlength[i - 1] + 1;
// 果map添加该字符和位置
myMap.put(str[i], i);
} else {
int aPos = lastPosOfChar + 1;
int unRepeatLen = strlength[i - 1];
int bPos = i - unRepeatLen;
if (aPos >= bPos) {
// 当前位置的最长无重复子串长度
strlength[i] = i - aPos + 1;
} else {
// 当前位置的最长无重复子串长度
strlength[i] = i - bPos + 1;
}
// 跟新当前字符出现的位置
myMap.put(str[i], i);
}
}
for (int i : strlength) {
temp = Math.max(temp, i);
}
}
return temp;
}
总结:Map大法好,应当努力学习一个。