Given a string, find the length of the longest substring without repeating characters.

Example 1:

Input: "abcabcbb"
Output: 3 
Explanation: The answer is "abc", with the length of 3. 

Example 2:

Input: "bbbbb"
Output: 1
Explanation: The answer is "b", with the length of 1.

Example 3:

Input: "pwwkew"
Output: 3
Explanation: 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.

 

暴力搜索

这道题乍一看很简单,因为是返回长度,因此考虑从长到短搜索,搜索到没有重复的直接返回就可以。

 

 1 public class Solution {
 2     public int LengthOfLongestSubstring(string s) {
 3         if (string.IsNullOrEmpty(s)) return 0;
 4         int length = s.Length;
 5         if (length == 1) return 1;
 6         while(length > 1)
 7         {
 8             for (int i = 0; i < s.Length - length + 1; i++)
 9             {
10                 if (IsNoneRepeatCharString(s.Substring(i,length)))
11                     return length;
12             }
13             length--;
14         }
15         return 1;
16     }
17     
18     private bool IsNoneRepeatCharString(string s)
19     {
20         HashSet<char> charSet = new HashSet<char>();
21         foreach (char c in s)
22         {
23             if (charSet.Contains(c)) return false;
24             charSet.Add(c);
25         }
26         return true;
27     }
28 }

 

Submit后发现超时了,testcase是一个巨长的字符串。

上面的方法虽然不用遍历所有子串,但到底来说还是Brute,时间复杂度还是O(n3)。

主要问题出现在判断重复子串的方法上,其实做了很多不必要的计算。

 

使用双指针的滑窗法

对于字符串"abcabd"来说,判断完子串"abc"后只要再判断下一个字符在不在上一个子串中。

控制两个指针start和end,当下一个字符在子串中存在时,更新start的位置。

 1 public class Solution {
 2     public int LengthOfLongestSubstring(string s) {
 3         //if (string.IsNullOrEmpty(s)) return 0;
 4         int length = s.Length;
 5         Dictionary<char, int> dict = new Dictionary<char, int>();
 6         int result = 0;
 7         for (int start = 0, end = 0; end < length; end++)
 8         {
 9             if (dict.ContainsKey(s[end]))
10             {
11                 start = Math.Max(start, dict[s[end]]);
12                 dict[s[end]] = end + 1;
13             }
14             else
15             {
16                 dict.Add(s[end], end + 1);
17             }
18             result = Math.Max(result, end - start + 1);
19         }
20         return result;
21     }
22 }