leetcode 第3題 無重複字元的最長子串

2021-09-17 20:48:38 字數 3627 閱讀 6949

說明:部分文字解析來自於原文。

一、暴力解法【時間複雜度o(n^3)】

二、滑動視窗【時間複雜度為o(n)】

三、優化的滑動視窗

給定乙個字串,請你找出其中不含有重複字元的 最長子串 的長度。

示例 1:

輸入: "abcabcbb"

輸出: 3

解釋: 因為無重複字元的最長子串是 "abc",所以其長度為 3。

示例 2:

輸入: "bbbbb"

輸出: 1

解釋: 因為無重複字元的最長子串是 "b",所以其長度為 1。

示例 3:

輸入: "pwwkew"

輸出: 3

解釋: 因為無重複字元的最長子串是 "wke",所以其長度為 3。

請注意,你的答案必須是 子串 的長度,"pwke"是乙個子串行,不是子串。

思路:和leetcode第五題:求最長回文子串 的思路很像,都是遍歷字串的所有子串,找出長度最大的那個無重複字元的子串。為了減少遍歷的次數,可以從長度最長的字串開始遍歷,這樣只要找到不包含重複字元的子串,就可以停止遍歷了。

// 暴力解法:判斷所有的子串是否是無重複字元的子串,從最長的開始

public static int getlengthoflongestsubstring1(string str)

int len = str.length();

int maxsublen = 0;

for(int i = 0; i < len; i++)}}

system.out.println(maxsublen);

return maxsublen;

}public static boolean allunique(string str, int start, int end)

set.add(ch);

}return true;}}

在暴力法中,我們會反覆檢查乙個子字串是否含有有重複的字元,但這是沒有必要的。如果從索引 i 到 j - 1 之間的子字串 s已經被檢查為沒有重複字元。我們只需要檢查 s[j] 對應的字元是否已經存在於子字串 s 中。

要檢查乙個字元是否已經在子字串中,我們可以檢查整個子字串,這將產生乙個複雜度為 o(n^2)的演算法,但我們可以做得更好。通過使用 hashset 作為滑動視窗,我們可以用 o(1) 的時間來完成對字元是否在當前的子字串中的檢查。

滑動視窗是陣列/字串問題中常用的抽象概念。 視窗通常是在陣列/字串中由開始和結束索引定義的一系列元素的集合,即 [i, j)(左閉,右開)。而滑動視窗是可以將兩個邊界向某一方向「滑動」的視窗。例如,我們將 [i,j) 向右滑動 1 個元素,則它將變為 [i+1, j+1)(左閉,右開)。

回到我們的問題,我們使用 hashset 將字元儲存在當前視窗 [i, j)(最初 j = i)中。 然後我們向右側滑動索引 j,如果它不在 hashset 中,我們會繼續滑動 j。直到 s[j] 已經存在於 hashset 中。此時,我們找到的沒有重複字元的最長子字串將會以索引 i 開頭。如果我們對所有的 i 這樣做,就可以得到答案。

// 滑動視窗:視窗內的都是已經判斷過的沒有重複字元的子串,無需重新判斷,從而減少判斷的次數

public static int getlengthoflongestsubstring3(string str)

int len = str.length();

setset = new hashset<>();

int maxsublen = 0, i = 0, j = 0;

// 視窗是從0位置開始的,視窗會慢慢擴大,直到遇見含重複的子串,視窗會減小,處在視窗中的字元都是不重複的,無需再進行判斷

while(i < len && j < len)else

}system.out.println(maxsublen);

return maxsublen;}}

複雜度分析其實對於上訴的滑動視窗的做法還可以做到優化,主要優化的點是:當找到s[j] 在 s 中存在乙個重複的字元 j',這個時候不是讓 i++ ,一直超過 j',而是直接將 i 的位置設定為 j' + 1,跳過 [i, j'] 這個範圍。相當於遇到重複字元時視窗不是逐漸減小的,而是一步減小到不包含 s[j] 的大小。

我們可以使用 hashmap 定義字元到索引的對映,而不是使用集合來判斷乙個字元是否存在。

public class lengthoflongestsubstring_3 

// 優化的滑動視窗

public static int getlengthoflongestsubstring4(string str)

int len = str.length(), maxsublen = 0;

mapmap = new hashmap<>();

for(int j = 0, i = 0; j < len; j++)

maxsublen = math.max(maxsublen, j - i + 1);

map.put(str.charat(j), j + 1);

}system.out.println(maxsublen);

return maxsublen;}}

leetcode 第3題 無重複字元的最長字串

給定乙個字串,請你找出其中不含有重複字元的 最長子串 的長度。注意 區分字串和子串行,子串必須相鄰,子串行不一定 用乙個陣列實現hashmap,key為字元,value為字元最後出現的位置,初始化為 1。陣列大小 因為ascii表只有256個字元,然而鍵盤只能表示128個,所以用128也行。用乙個 ...

Leetcode刷題之路 3 無重複的最長字串

給定乙個字串,請你找出其中不含有重複字元的 最長子串 的長度。示例 1 輸入 abcabcbb 輸出 3 解釋 因為無重複字元的最長子串是 abc 所以其長度為 3。示例 2 輸入 bbbbb 輸出 1 解釋 因為無重複字元的最長子串是 b 所以其長度為 1。示例 3 輸入 pwwkew 輸出 3 ...

LeetCode刷題 3 無重複字元的最長字串

給定乙個字串,請你找出其中不含有重複字元的 最長子串 的長度。示例 1 輸入 abcabcbb 輸出 3 解釋 因為無重複字元的最長子串是 abc 所以其長度為 3。示例 2 輸入 bbbbb 輸出 1 解釋 因為無重複字元的最長子串是 b 所以其長度為 1。示例 3 輸入 pwwkew 輸出 3 ...