hot100-一刷-03滑動視窗(共2道題)

chendsome發表於2024-12-03

3. 無重複字元的最長子串

題目連結

題目描述

image

程式碼實現

分析:因為是要連續的序列,使用滑動視窗 + 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. 找到字串中所有字母異位詞

題目連結

題目描述

image

程式碼實現

分析:
初始化時維護一個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;
    }
}

相關文章