给定一个字符串,找出不含有重复字符的最长子串的长度。
示例:
给定 "abcabcbb"
,没有重复字符的最长子串是 "abc"
,那么长度就是3。
给定 "bbbbb"
,最长的子串就是 "b"
,长度是1。
给定 "pwwkew"
,最长子串是 "wke"
,长度是3。请注意答案必须是一个子串,"pwke"
是 子序列 而不是子串。
自己的思路: 从第一个字符开始,每次遍历,都打入unorder_map中,用count函数判断是否出现过了,如果出现过就到此为止,证明从第一个字符最长的不重复子串就到这里。开始从第二个字符用同样的方法开始。然后再判断以各个字符为首的最大长度。这个做法时间太长。
int lengthOfLongestSubstring(string s) { if(s.empty()) return 0; int maxlength = 1; unordered_map<int,int> m; for(int k=0;k<s.size();k++) { m.erase(m.begin(),m.end()); int l=0; for(int i = k;i<s.size();i++) { if(m.count(s[i])) { break; } else { m[s[i]]=i; l++; } } maxlength = maxlength>l ? maxlength : l; } return maxlength; }
需要注意的地方是:在每次遍历时,map要清空,不然上次的遍历的结果会影响这次的判断。
还有一种更简单的做法。就是用一个数组去记录每个字符最后一次出现的位置,这样的话,我们只需要从头到尾遍历一次,每遍历一个字符,记录下当前的长度,并比较出最大长度,每个字符的起始位置都初始化为-1,在遍历的同时更新,如果该字符最后一次出现的位置比起始位置要大,那就意味着出现了重复元素,那下一个起始位置就要从当前算了。
int lengthOfLongestSubstring(string str) { int vis[130];//vis[i] 记录字符i最后一次出现的位置 memset(vis, -1, sizeof vis); int n = (int)str.size(); int ans = 0;//最后结果 int pre = -1; //记录当前不重复子串的起始位置 for (int i = 0; i < n; i ++) { // 比较当前字符最后一次出现的位置vis[str[i]]: // 如果大于pre(当前不重复子串的起始位置)那么子串的起始位置就要变成vis[str[i]] + 1了 // 如果小于pre,那么就无关紧要了,这个子串可以加入到不重复子串中 pre = pre > vis[str[i]] ? pre : vis[str[i]]; int cnt = i - pre; ans = ans < cnt ? cnt : ans; vis[str[i]] = i; } return ans; }