LeetCode 3. Longest Substring Without Repeating Characters
最初思路,也是最简单的思路,维护一个string res,保留当前的不重复的字符串。string s一位位读进,读进每一位时和res中的每一位进行比较,没有重复就加入res;重复了的话,res就只保留与s[i]重复的那个char右边的部分,并加上s[i],在对res进行截取操作之前更新maxLen。当string s读完后,再更新一次maxLen,因为可能整个string s都没有重复字符。
1 class Solution { 2 public: 3 int lengthOfLongestSubstring(string s) { 4 int maxLen = 0; 5 string res = ""; 6 for(int i = 0; i < s.length(); ++i){ 7 if(res == "") res += s[i]; 8 else{ 9 bool flag = true; 10 int pos = 0; 11 for(int j = 0; j < res.length(); ++j){ 12 if(s[i] == res[j]){ 13 flag = false; 14 pos = j; 15 break; 16 } 17 } 18 if(flag) res += s[i]; 19 else{ 20 int len = res.length(); 21 maxLen = max(maxLen, len); 22 res = res.substr(pos+1, res.length() - 1 - pos) + s[i]; 23 } 24 } 25 } 26 int len = res.length(); 27 return max(maxLen, len); 28 } 29 };
第二种思路,其实源于第一种,但加入了map这一数据类型,本以为可以减少时间,然而更慢了。
hash存放string s中每个char及其对应的位置,如果char出现多次,位置是最新出现的那一次。
维护两个变量l、r,分别表示无重复字符串的左右位置(包含关系,[l,r])。
每次读进s[r],如果已经在hash中了,更新l,l = max(l, hash[s[r]] + 1); 解释一下,假设和s[r]重复的是s[i],s[i]的位置可能在s[l]的左边(e.g.“tmmt” 第2个t读入时,l=2,而s[i] = t, i = 0),还有可能在s[l]的右边,那么l就跳到s[i]的右边一位,保证从l到r无char重复。
每次读进s[r]记得要更新hash中s[r]对应的位置,还要更新maxLen的值。(也可以每次遇到重复char再更新maxLen的值,写法不同而已)
1 class Solution { 2 public: 3 int lengthOfLongestSubstring(string s) { 4 map<char, int> hash; 5 int l = 0, r = 0; 6 int maxLen = 0; 7 while(r < s.length()){ 8 if(hash.find(s[r]) != hash.end()){ 9 l = max(l, hash[s[r]] + 1); 10 } 11 hash[s[r]] = r; 12 maxLen = max(maxLen, r - l + 1); 13 ++r; 14 } 15 return maxLen; 16 } 17 };
第三种,dp,应该是最快的,留坑。
https://leetcode.com/discuss/90845/my-6ms-java-solution-beating-85%25-with-explanation