3. Longest Substring Without Repeating Characters
- 暴力算法
- 哈希表
题目
Given a string, find the length of the longest substring without repeating characters.
Examples:
Given "abcabcbb"
, the answer is "abc"
, which the length is 3.
Given "bbbbb"
, the answer is "b"
, with the length of 1.
Given "pwwkew"
, the answer is "wke"
, with the length of 3. Note that the answer must be a substring, "pwke"
is a subsequence and not a substring.
思路
- 暴力算法:逐一遍历元素,找到没有重复字符的最大子串。
- 复杂性分析:
- 时间复杂度:O(n^2).
- 空间复杂度:O(n).
题解
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int strlen = s.size(), longlen = 0;
string temp;
for (int i=0; i < strlen; i++) {
int len = temp.size();
// 逐一添加新字符
temp.push_back(s[i]);
for (int j = 0; j < len; j++) {
if (temp[j] == s[i]) {
// 找到第一个重复字符则得到一个不重复子串
if (len > longlen) {
longlen = len;
}
// 从该子串中重复字符的后一个字符开始继续遍历寻找下一不重复子串
temp = temp.substr(j+1);
break;
}
}
}
if (temp.size() > longlen) {
longlen = temp.size();
}
return longlen;
}
};
优化
思路
上述方法的思路是将新添加的字符逐一与子串对比,这是一个查找匹配的过程,同样可以用哈希表将查询时间优化至O(1),将时间复杂度降至O(n)。
代码(WA,待修正)
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int strlen = s.size(), longlen = 0;
map<char, int> hashMap;
map<char, int>::iterator it;
for (int i=0; i < strlen; i++) {
it = hashMap.find(s[i]);
if (it != hashMap.end()) {
if (longlen < hashMap.size())
longlen = hashMap.size();
// 由于map元素的存放时是按照key值排序,所以这样的截取会存在问题,需要改进截取方式
hashMap.erase(hashMap.begin(), hashMap.find(s[it->second+1]));
}
hashMap[s[i]] = i;
}
if (hashMap.size() > longlen) {
longlen = hashMap.size();
}
return longlen;
}
};
反思
- 熟悉map的存放和操作。
存放:内部结构采用红黑树的平衡二叉树,系统会根据Key值来自动将数据排序存放。
iterator操作:和find等算法在一起使用的时候,需要牢记:不要使用过期的iterator。
以上反思,有待指教。