3.无重复字符的最长子串
给定一个字符串,找出不含有重复字符的最长子串的长度。
示例:
给定 "abcabcbb"
,没有重复字符的最长子串是 "abc"
,那么长度就是3。
给定 "bbbbb"
,最长的子串就是 "b"
,长度是1。
给定 "pwwkew"
,最长子串是 "wke"
,长度是3。请注意答案必须是一个子串,"pwke"
是 子序列 而不是子串。
解决方案1:
利用set集合的元素不重复性质,来进行重复性的判断。
我们可以看出,算法的时间复杂度比较高:O(n*n),提交的时候在原串特别长的情况下,会超时。
代码:
class Solution { public: int lengthOfLongestSubstring(string s) { int max = 0; for(int i = 0; i<s.length(); i++) for(int j = i+1; j<=s.length(); j++) if(Isrepeat(s,i,j) && (max<j-i)) max = j-i; return max; } bool Isrepeat(string s, int start, int end){ std::set<char> set; //定义一个set集合 char tmp; //用于读取每一个字符串 for(int i = start; i<end; i++){ tmp = s[i]; if (set.find(tmp) != set.end()) //如果不相等,即表示这个字符在set集合中已经存在 return false; set.insert(tmp); } return true; } }; |
借助hashmap来解决,map的键key存放字符串中出现的字符,值value存放该字符当前的位置。
首先创建一个头指针now,指向当前子串的开头,maxLength保存当前最大长度;刚开始,now指向字符串的第一个字符,随着遍历字符串,如果map中不包含当前字符,那么now不变,用字符当前位置和now的位置相减,然后再与最大长度进行比较,更新maxLength;再将当前字符以及它的位置保存到map中;如果map中包含当前字符,则需改变头指针now所指的位置(将头指针now当前位置与map中当前字符所存位置的下一个位置进行比较,选择最大者作为最新头指针所指位置),然后再更新maxLength,再将map中当前字符的位置更新。
总的来说:不管map中有无当前字符,都需在map中更新,记录字符最近出现的位置。
比如:abba
(1)初始:maxLength=0;
(2)abba:map中不含该字符, now 指向第一个a; map中添加该字符及其位置,<a,0>; maxLength=1;
(3)abba: map中不含该字符,now指向第一个a; map中添加该字符及其位置,<b,1>; maxLength=2;
(4)abba: map中含有相同字符b,now更新,指向2 { [(map中b的位置为1 ) +1 ] > (now=0)};map中更新该字符及其位置,<b,2>; maxLength=2;
(5)abba: map中含有该字符,更新map种该字符最新位置,<a,3>;now指向第二个b,maxLength=2;
代码:
class Solution { public int lengthOfLongestSubstring(String s) { //map中的键key存放字符串中出现的字符,值value存放该字符当前的位置 Map<Character,Integer> map = new HashMap<Character,Integer>(); int now = 0; //记录头指针位置 for(int i=0; i<s.length(); i++ ){ if(map.containsKey(s.charAt(i))){ //如果map中已存在当前字符 //更新当前指针位置,如果当前指针大,则使用当前指针,否则使用该指针下一个字符的位置 if((i-now+1) > maxLength) maxLength = i-now+1; } else //map中不存在当前字符 if((i-now+1) > maxLength) //更新最长字串的长度maxLength = i-now+1; map.put(s.charAt(i), i);//修改当前字符的value,记录最新位置 } return maxLength; } } |