3. 無重複字元的最長子串
題目連結
題目描述
程式碼實現
分析:因為是要連續的序列,使用滑動視窗 + Set集合來判斷即將要加入視窗右端的元素是已經在視窗中出現過。
程式碼:
class Solution {
public int lengthOfLongestSubstring(String s) {
int ans = 0;
// Set去重
Set<Character> set = new HashSet<>();
// 滑動視窗
char[] chars = s.toCharArray();
int left = 0;
int right = 0;
for (; right < s.length(); right++){
// left < right 也可以不加。 最壞的情況,是left在right前一位
// 相當於先把該元素移出set, while外又加進set,並且此時left=right, for裡right再++
while(left < right && set.contains(chars[right])){
set.remove(chars[left]);
left++;
}
set.add(chars[right]);
// 更新每一輪新增元素時的最大子串長度
ans = Math.max(ans, right - left + 1);
}
return ans;
}
}
模板
題解區有人提到滑動視窗的模板題,
//外層迴圈擴充套件右邊界,內層迴圈擴充套件左邊界
for (int l = 0, r = 0 ; r < n ; r++) {
//當前考慮的元素
while (l <= r && check()) {//區間[left,right]不符合題意
//擴充套件左邊界
}
//區間[left,right]符合題意,統計相關資訊
}
// ----------------------------------------
class Solution {
public int lengthOfLongestSubstring(String s) {
//滑動視窗
char[] ss = s.toCharArray();
Set<Character> set = new HashSet<>();//去重
int res = 0;//結果
for(int left = 0, right = 0; right < s.length(); right++) {//每一輪右端點都擴一個。
char ch = ss[right];//right指向的元素,也是當前要考慮的元素
while(set.contains(ch)) {//set中有ch,則縮短左邊界,同時從set集合出元素
set.remove(ss[left]);
left++;
}
set.add(ss[right]);//別忘。將當前元素加入。
res = Math.max(res, right - left + 1);//計算當前不重複子串的長度。
}
return res;
}
}
438. 找到字串中所有字母異位詞
題目連結
題目描述
程式碼實現
分析:
初始化時維護一個pLen大小的視窗,使用陣列來記錄字母出現的次數。
程式碼:
class Solution {
public List<Integer> findAnagrams(String s, String p) {
// s 長度小於 p 必然不行
if(s.length() < p.length()) return new ArrayList<>();
List<Integer> ans = new ArrayList<>();
int[] arrS = new int[26];
int[] arrP = new int[26];
// 初始化時維護一個pLen大小的視窗
for(int i = 0; i < p.length(); i++){
// 記錄p裡所有字母出現的次數
arrP[p.charAt(i) - 'a']++;
arrS[s.charAt(i) - 'a']++;
}
if(Arrays.equals(arrP,arrS)){
ans.add(0);
}
for(int i = 0; i < s.length() - p.length(); i++){
// 頭出
arrS[s.charAt(i) - 'a']--;
// 尾進
arrS[s.charAt(i + p.length()) - 'a']++;
// 新頭滿足則新增到ans,不滿足就再判斷下一輪
if(Arrays.equals(arrP,arrS)){
ans.add(i+1);
}
}
return ans;
}
}