您的位置:首页 > 其它

[LeetCode] Longest Substring Without Repeating Characters

2014-11-23 13:34 375 查看
Given a string, find the length of the longest substring without repeating characters. For example, the longest substring without repeating letters for "abcabcbb" is "abc", which the length is 3. For "bbbbb" the longest substring is "b", with the length of 1.

这道题经过了一番苦苦挣扎还是没能解出来。虽然借助哈希表可以弄到O(n^2)但是题目要求是O(n),感觉有用点DP的技巧,其实基本思想就是当遇到重复的时候,不用从下一个字符开始搜索。举个栗子:

abcdefdh

高亮的是目前处理到的最长不重复子串,现在处理到d的时候,发现了重复,此时我们没有必要从b 开始重新搜索,而是算出两个d 之间有多少字符,这些字符可以组成新的不重复子串参与到下一次搜索中,这里我们有ef 两个字符,加上新来的d,就是3个字符,这个很好算:通过两个d 的id相减就可以了(6-3=3)

这里我遇到的问题是,怎么在新的一轮搜索中更新hash表的内容,因为新的最长不重复子串是efd,前面的abcd就应该从hash表中移除。但是移除操作本身是O(n)的,没法做到O(1)。。。于是就陷进去了。

最后看了答案,发现思路是很相似的,怎么解决我上面遇到的问题呢?就是维护“最后出现位置”的机制,这样我们就不用去纠结怎么把hash表里的东西删掉了,只用每次都更新hash表里对应字符的id。接着上面的栗子说:

当遇到第二个d 的时候,我们不仅检查d 是否在hash表中,而且还要检查当前index(6)减去目前最长不重复子串长度(3)是否小于等于d 在hash 表中对应的id(3) 这里:6-3 <= 3 就说明上一个d确实包含在当前的最长不重复子串中。

说的有点糊涂。。直接看代码可能还清晰点:

int lengthOfLongestSubstring(string s) {
int n = (int)s.size();
if (!n) return 0;
int len = 0, max = 0;
unordered_map<char, int> map;

for (int i = 0; i < n; i++) {
if (map.find(s[i]) == map.end() || map[s[i]] < i - len) {
len++;
}
else {
if (len > max) { max = len; }
len = i - map[s[i]];
}
map[s[i]] = i;
}
return len > max ? len : max;
}


O(n^2)的解法:

int lengthOfLongestSubstring(string s) {
if (!s.size()) return 0;
int len = 0;
int max = 0;
unordered_map<char, int>set;

for (int i = 0; i < s.size(); i++) {
if (s.size()-i-1 < max) break;
for (int j = i; j < s.size(); j++) {
if (set.find(s[j]) == set.end()) {
len++;
set[s[j]] = j;
}
else {
i = set[s[j]];
break;
}
}
if (len > max) {
max = len;
}
set.clear();
len = 0;
}

return max;
}


O(n^2)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: