給定一個字符串,請你找出其中不含有重複字符的 最長子串 的長度。
示例 1:
輸入: "abcabcbb"
輸出: 3
解釋: 因為無重複字符的最長子串是 "abc",所以其長度為 3。示例 2:
輸入: "bbbbb"
輸出: 1
解釋: 因為無重複字符的最長子串是 "b",所以其長度為 1。示例 3:
輸入: "pwwkew"
輸出: 3
解釋: 因為無重複字符的最長子串是 "wke",所以其長度為 3。
請注意,你的答案必須是 子串 的長度,"pwke" 是一個子序列,不是子串。
難度:支持語言:JavaScript、Java、Python、C++相關標籤相關企業思路題目要求連續, 我們考慮使用滑動窗口。而這道題就是窗口大小不固定的滑動窗口題目,然後讓我們求滿足條件的窗口大小的最大值,這是一種非常常見的滑動窗口題目。
算法:用一個 hashmap 來建立字符和其出現位置之間的映射。同時維護一個滑動窗口,窗口內的都是沒有重複的字符,去儘可能的擴大窗口的大小,窗口不停的向右滑動。
如果當前遍歷到的字符從未出現過,那麼直接擴大右邊界;
如果當前遍歷到的字符出現過,則縮小窗口(左邊索引向右移動),然後繼續觀察當前遍歷到的字符;
維護一個全局最大窗口 res,每次用出現過的窗口大小來更新結果 res,最後返回 res 獲取結果;
(圖片來源:https://github.com/MisterBooo/LeetCodeAnimation)
維護數組:使用一個數組來維護滑動窗口,遍歷字符串,判斷字符是否在滑動窗口數組裡
在則刪除滑動窗口數組裡相同字符及相同字符前的字符,然後將當前字符 push 進數組滑動窗口 暴力解法:暴力解法時間複雜度較高,會達到 O(n^2)O(n 2),故而採取滑動窗口的方法降低時間複雜度定義一個 map 數據結構存儲 (k, v),其中 key 值為字符,value 值為字符位置 +1,加 1 表示從字符位置後一個才開始不重複我們定義不重複子串的開始位置為 start,結束位置為 end隨著 end 不斷遍歷向後,會遇到與 [start, end] 區間內字符相同的情況,此時將字符作為 key 值,獲取其 value 值,並更新 start,此時 [start, end] 區間內不存在重複字符無論是否更新 start,都會更新其 map 數據結構和結果 ans。關鍵點滑動窗口記錄當前 index 開始的最大的不重複的字符序列複雜度分析代碼JavaScript 實現/**
* @作者:user7746o
* @連結:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/zi-jie-leetcode3wu-zhong-fu-zi-fu-de-zui-chang-zi-/
*/
var lengthOfLongestSubstring = function(s) {
let arr = [], max = 0
for(let i = 0; i < s.length; i++) {
let index = arr.indexOf(s[i])
if(index !== -1) {
arr.splice(0, index+1);
}
arr.push(s.charAt(i))
max = Math.max(arr.length, max)
}
return max
};/**
* @作者:Heternally
* @連結:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/javascriptjie-fa-chao-9998-by-heternally/
*/
var lengthOfLongestSubstring = function(s) {
let num = 0,res = 0;
let m = '';
for (n of s) {
if (m.indexOf(n) == -1) {
m += n;
num++;
res = res < num ? num: res;
} else {
m += n;
m = m.slice(m.indexOf(n)+1);
num = m.length;
}
}
return res;
};
C++ 實現class Solution {
public:
int lengthOfLongestSubstring(string s) {
int ans = 0, start = 0;
int n = s.length();
//
map<char, int> mp;
for(int i=0;i<n;i++)
{
char alpha = s[i];
if(mp.count(alpha))
{
start = max(start, mp[alpha]+1);
}
ans = max(ans, i-start+1);
// 字符位置
mp[alpha] = i;
}
return ans;
}
};/**
* @作者:LeetCode-Solution
* @連結:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/wu-zhong-fu-zi-fu-de-zui-chang-zi-chuan-by-leetc-2/
*/
class Solution {
public:
int lengthOfLongestSubstring(string s) {
// 哈希集合,記錄每個字符是否出現過
unordered_set<char> occ;
int n = s.size();
// 右指針,初始值為 -1,相當於我們在字符串的左邊界的左側,還沒有開始移動
int rk = -1, ans = 0;
// 枚舉左指針的位置,初始值隱性地表示為 -1
for (int i = 0; i < n; ++i) {
if (i != 0) {
// 左指針向右移動一格,移除一個字符
occ.erase(s[i - 1]);
}
while (rk + 1 < n && !occ.count(s[rk + 1])) {
// 不斷地移動右指針
occ.insert(s[rk + 1]);
++rk;
}
// 第 i 到 rk 個字符是一個極長的無重複字符子串
ans = max(ans, rk - i + 1);
}
return ans;
}
};/**
* @作者:pinku-2
* @連結:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/wu-zhong-fu-zi-fu-de-zui-chang-zi-chuan-cshi-xian-/
*/
class Solution
{
public:
int lengthOfLongestSubstring(string s)
{
//s[start,end) 前面包含 後面不包含
int start(0), end(0), length(0), result(0);
int sSize = int(s.size());
while (end < sSize)
{
char tmpChar = s[end];
for (int index = start; index < end; index++)
{
if (tmpChar == s[index])
{
start = index + 1;
length = end - start;
break;
}
}
end++;
length++;
result = max(result, length);
}
return result;
}
};
Java 實現暴力解法時間複雜度較高,會達到 O(n^2)O(n2 ),故而採取滑動窗口的方法降低時間複雜度定義一個 map 數據結構存儲 (k, v),其中 key 值為字符,value 值為字符位置 +1,加 1 表示從字符位置後一個才開始不重複我們定義不重複子串的開始位置為 start,結束位置為 end隨著 end 不斷遍歷向後,會遇到與 [start, end] 區間內字符相同的情況,此時將字符作為 key 值,獲取其 value 值,並更新 start,此時 [start, end] 區間內不存在重複字符無論是否更新 start,都會更新其 map 數據結構和結果 ans。class Solution {
public int lengthOfLongestSubstring(String s) {
int ans = 0, start = 0;
int n = s.length();
//
Map<Character, Integer> map = new HashMap<>();
for(int i=0;i<n;i++)
{
char alpha = s.charAt(i);
if(map.containsKey(alpha))
{
start = Math.max(start, map.get(alpha)+1);
}
ans = Math.max(ans, i-start+1);
// 字符位置
map.put(alpha, i);
}
return ans;
}
}/**
* @作者:guanpengchn
* @連結:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/hua-jie-suan-fa-3-wu-zhong-fu-zi-fu-de-zui-chang-z/
*/
class Solution {
public int lengthOfLongestSubstring(String s) {
int n = s.length(), ans = 0;
Map<Character, Integer> map = new HashMap<>();
for (int end = 0, start = 0; end < n; end++) {
char alpha = s.charAt(end);
if (map.containsKey(alpha)) {
start = Math.max(map.get(alpha), start);
}
ans = Math.max(ans, end - start + 1);
map.put(s.charAt(end), end + 1);
}
return ans;
}
}/**
* @作者:VioletKiss
* @連結:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/javati-jie-3wu-zhong-fu-zi-fu-de-zui-chang-zi-chua/
*/
class Solution {
public int lengthOfLongestSubstring(String s) {
int i = 0;
int flag = 0;
int length = 0;
int result = 0;
while (i < s.length()) {
int pos = s.indexOf(s.charAt(i),flag);
if (pos < i) {
if (length > result) {
result = length;
}
if (result >= s.length() - pos - 1) {
return result;
}
length = i - pos - 1;
flag = pos + 1;
}
length++;
i++;
}
return length;
}
}
Python3 實現from collections import defaultdict
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
l = 0
ans = 0
counter = defaultdict(lambda: 0)
for r in range(len(s)):
while counter.get(s[r], 0) != 0:
counter[s[l]] = counter.get(s[l], 0) - 1
l += 1
counter[s[r]] += 1
ans = max(ans, r - l + 1)
return ans
# @作者:powcai
# @連結:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/hua-dong-chuang-kou-by-powcai/
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if not s:return 0
left = 0
lookup = set()
n = len(s)
max_len = 0
cur_len = 0
for i in range(n):
cur_len += 1
while s[i] in lookup:
lookup.remove(s[left])
left += 1
cur_len -= 1
if cur_len > max_len:max_len = cur_len
lookup.add(s[i])
return max_len
# @作者:marcusxu
# @連結:連結:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/solution/python3ti-jie-chao-jian-dan-de-dong-tai-gui-hua-ji/
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if s == '':
return 0
if len(s) == 1:
return 1
def find_left(s, i):
tmp_str = s[i]
j = i - 1
while j >= 0 and s[j] not in tmp_str:
tmp_str += s[j]
j -= 1
return len(tmp_str)
length = 0
for i in range(0, len(s)):
length = max(length, find_left(s, i))
return length
其他原題leetcode連結:3.longest-substring-without-repeating-characters合作方:JavaScript中文網 – 全球極客摯愛的技術成長平臺說明:leetcode 題解 | 每日一題🔥 所有題目並非全部為本人解答,部分為在複習學習中整理提取其他解題作者的優秀筆記,便於大家學習共同進步,如有侵權,請聯繫刪除。