題目鏈接
tag:
- Medium;
question:
??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.
思路:
??給了一個字符串旺罢,讓求最長的無重復字符的子串壳坪,注意這里是子串读整,不是子序列宾舅,所以必須是連續(xù)的在验。我們先不考慮代碼怎么實現(xiàn),拿Example1中的例子"abcabcbb"绩社,該怎么找摔蓝。博主會一個字符一個字符的遍歷,比如a愉耙,b项鬼,c,然后又出現(xiàn)了一個a劲阎,那么此時就應該去掉第一次出現(xiàn)的a,然后繼續(xù)往后鸠真,又出現(xiàn)了一個b悯仙,則應該去掉一次出現(xiàn)的b龄毡,以此類推,最終發(fā)現(xiàn)最長的長度為3锡垄。所以說沦零,我們需要記錄之前出現(xiàn)過的字符,記錄的方式有很多货岭,最常見的是統(tǒng)計字符出現(xiàn)的個數(shù)路操,但是這道題字符出現(xiàn)的位置很重要,所以我們可以使用HashMap來建立字符和其出現(xiàn)位置之間的映射千贯。進一步考慮屯仗,由于字符會重復出現(xiàn),到底是保存所有出現(xiàn)的位置呢搔谴,還是只記錄一個位置魁袜?我們之前手動推導的方法實際上是維護了一個滑動窗口,窗口內(nèi)的都是沒有重復的字符敦第,我們需要盡可能的擴大窗口的大小峰弹。由于窗口在不停向右滑動,所以我們只關心每個字符最后出現(xiàn)的位置芜果,并建立映射鞠呈。窗口的右邊界就是當前遍歷到的字符的位置,為了求出窗口的大小右钾,我們需要一個變量left來指向滑動窗口的左邊界蚁吝,這樣那么就分兩種情況,在或不在滑動窗口內(nèi)霹粥,如果不在滑動窗口內(nèi)灭将,那么就沒事,當前字符可以加進來后控,如果在的話庙曙,就需要先在滑動窗口內(nèi)去掉這個已經(jīng)出現(xiàn)過的字符了,去掉的方法并不需要將左邊界left一位一位向右遍歷查找浩淘,由于我們的HashMap已經(jīng)保存了該重復字符最后出現(xiàn)的位置捌朴,所以直接移動left指針就可以了。我們維護一個結(jié)果res张抄,每次用出現(xiàn)過的窗口大小來更新結(jié)果res砂蔽,就可以得到最終結(jié)果啦。AC代碼如下:
C++ 解法:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
if (s.size() < 2)
return s.size();
unordered_map<char, int> m;
int max_len = 0, left = -1;
for (int i=0; i<s.size(); ++i) {
if (m.count(s[i]) && m[s[i]] > left)
left = m[s[i]];
m[s[i]] = i;
max_len = max(max_len, i-left);
}
return max_len;
}
};
Python 解法:
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if len(s) < 2:
return len(s)
d = {}
left = -1
max_len = 0
for i in range(len(s)):
if s[i] in d and d[s[i]] > left:
left = d[s[i]]
d[s[i]] = i
max_len = max(max_len, i-left)
return max_len