在拿到這個題目我第一時間想的是用map統計字符串中字符出現的情況,然后記錄最長子串寫出程序如下:
static const auto io_speed_up = []() { std::ios::sync_with_stdio(false); cin.tie(nullptr); return 0; }(); class Solution { public: int lengthOfLongestSubstring(string s) { char c; int begin = 0; int maxLength = 0; int nowLength = 0; size_t length = s.length(); unordered_map<char, int> strMap{ {'a', -1}, {'b', -1}, {'c', -1}, {'d', -1}, {'e', -1}, {'f', -1}, {'g', -1}, {'h', -1}, {'i', -1}, {'j', -1}, {'k', -1}, {'l', -1}, {'m', -1}, {'n', -1}, {'o', -1}, {'p', -1}, {'q', -1}, {'r', -1}, {'s', -1}, {'t', -1}, {'u', -1}, {'v', -1}, {'w', -1}, {'x', -1}, {'y', -1}, {'z', -1} }; for (size_t i = 0; i < length; ++i) { c = s.at(i); if (strMap[c] == -1) { ++nowLength; strMap[c] = i; } else { maxLength = maxLength > nowLength ? maxLength : nowLength; nowLength -= (strMap[c] - begin); while (begin <= strMap[c]) { strMap[s.at(begin)] = -1; ++begin; } strMap[c] = i; } } return maxLength > nowLength ? maxLength : nowLength; } };
但是提交之后發現只快於65.17%的程序,就去看了一下最優解,最優解代碼如下:
static const auto io_speed_up = []() { std::ios::sync_with_stdio(false); cin.tie(nullptr); return 0; }(); class Solution { public: int lengthOfLongestSubstring(string s) { int size = s.size(); vector<int> dict(256,-1); int maxlen = 0; int start = -1; for (int i=0;i<size;i++) { if (dict[s[i]] > start) { start = dict[s[i]]; } dict[s[i]] = i; maxlen = max(maxlen, i - start); } return maxlen; } };
二者思路相似都是通過對應字符串中的字符出現,當出現重復字符時,拋棄重復出現的字符前一次出現的位置,把新的子串開始位置設置為其+1來統計子串長度,最后得出最長的子串長度。執行速度區別我認為出現在以下兩個方面:
一是開辟了一個長度為256(char型最多為256)的vector數組來比較字符,這樣可以充分得利用數據的局部性,加快內存讀取速度。
二是他的比較方式是比較新出現的字符是否比上個字符出現的位置更遠,之后直接替換。而我是比較字符對應的出現節點是否是初始化為-1的如果是,那么替換,這樣我在出現重復字符的時候就要對前面的字符串進行重置,這里多了循環次數。
有時候不得不承認,別人寫的程序比你短,比你容易理解,執行效率還比你高。sad。