3. 最长无重复子串Longest Substring Without Repeating Characters
Given a string, find the length of the longest substring without repeating characters. 找出字串S中最长无重复子串的长度。
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.法一:C++
class Solution { public: int lengthOfLongestSubstring(string s) { if(s.size()<2) return s.size(); //如果长度小于2 ,返回自身长度(有一个或零个元素) int d=1, maxLen=1; //d存放两个相同元素的距离,如adlgdo,中d的相距距离是d = 3,所以有个无重复元素的串是“dlg”,长度是3 unordered_map<char,int> map; //存放元素最新出现的位置 map[s[0]]=0; //第一个元素出现的位置自然是0 for(int i=1;i<s.size();i++){ if(map.count(s[i])==0 || map[s[i]]<i-d) //如果这个元素出现次数为零。或者这个元素出现过,但是已经处理过(说明已经成对出现过) d++; else //表示这个元素出现过,从i开始, d= i- map[s[i]]; map[s[i]]=i; //记录当前元素出现的位置 if(d>maxLen) maxLen = d; } return maxLen; } };
法二:
- 第一步:计算所有的子串,子串可以从S的下标 i 开始,到 j 结束(0≤i<j≤n )即 i 取值范围[ 0, n-1 ],j 取值范围[ 1, n ];
- 第二步:对S的所有子串“查重”。。方法是利用一个set集,每查重一个子串s,用一个新的空set。从 i 到 j 依次把子串s的字母存进set,存之前查看这个字母是否已存在于set,有的话,返回false,否则返回true
Java public class Solution { public int lengthOfLongestSubstring(String s) { int n = s.length(); int ans = 0; for (int i = 0; i < n; i++) for (int j = i + 1; j <= n; j++) if (allUnique(s, i, j)) ans = Math.max(ans, j - i); //ans存的是目前最大子串长度,j - i 代表当前子串长度 return ans; } public boolean allUnique(String s, int start, int end) { //相当于上边步骤2 Set<Character> set = new HashSet<>(); for (int i = start; i < end; i++) { Character ch = s.charAt(i); if (set.contains(ch)) return false; set.add(ch); } return true; } }
此方法时间复杂度,比较高,O(n3)。