LeetCode #3 Longest Substring Without Repeating Characters
Description
Given a string, find the length of the longest substring without repeating characters.
題意
給定一個字符串,求出不帶重復字符的最長子串的長度。
Example
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"pwke"
is a subsequence and not a substring.
思路
這道題涉及查找,肯定是使用哈希表是最快的。假設Key 是字符串中的字符,Value 是長度,每次掃描時令鍵與當前掃描到的字符匹配,如果重復了就不加入 Map,最後輸出 longth。但是這樣的辦法有問題,因為它求出來的是子序列而不是子串,樣例3通不過,顯示輸出的是4。
//Note:This is Wrong Answer !!! #include<unordered_map> using std::unordered_map;class Solution { public: int lengthOfLongestSubstring(string s) { unordered_map<char,int> um; int i; int n = s.size(); int longth = 0; for (i = 0; i < n; ++i) { if (um.find(s[i]) != um.end()) { continue; }else{ um[s[i]] = ++longth; } } um.clear(); return longth; } };
隨後,我再思考了一遍題目,發現其實這題可以想象成一個隊列,每次入隊時都需要查看隊裏有沒有重復的字符,若有則將重復的字符及其之前的字符給刪去,這樣就可以保證隊內沒有重復的字符了。那麽問題就來了,如何去模擬這樣一個隊列?
我們可以用1個 set 和 兩個哨兵 i j 去模擬一個隊列。set (集合)是一個 key 與 value 必須相等的數據結構,用它的原因是它可以用紅黑樹或哈希表實現,查找效率高一些。哨兵 i 表示子串左端,哨兵 j 表示子串右端,每一輪掃描都在 set 的鍵中查找 s[j] 是否存在,若不存在則在 set 中增加元素 s[j] 且 j++,若存在則在集合 set 中刪去元素 s[i] 且 i++,這樣就實現了一個隊列的操作,一段出,一段入。
如何求最長子串呢?在每一輪中實時比較子串長度並更新記錄 res即可。
//Runtime: 46 ms
#include<set> #include<algorithm> using std::set; using std::max; class Solution { public: int lengthOfLongestSubstring(string s) { set<char> mySet; int res = 0, temp = 0; int i = 0,j = 0; int n = s.size(); while (j < s.size()) { if (mySet.find(s[j]) != mySet.end()) { mySet.erase(s[i]); ++i; } else { mySet.insert(s[j]); ++j; } temp = mySet.size(); res = max(res, temp); } mySet.clear(); return res; } };
感覺我的方法還是有些慢,如果有更好的辦法歡迎討論。
LeetCode #3 Longest Substring Without Repeating Characters