面試題_滑動窗口

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

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

示例 1:

輸入: s = "abcabcbb"
輸出: 3
解釋: 因爲無重複字符的最長子串是 "abc",所以其長度爲 3。
示例 2:

輸入: s = "bbbbb"
輸出: 1
解釋: 因爲無重複字符的最長子串是 "b",所以其長度爲 1。
示例 3:

輸入: s = "pwwkew"
輸出: 3
解釋: 因爲無重複字符的最長子串是 "wke",所以其長度爲 3。
請注意,你的答案必須是 子串 的長度,"pwke" 是一個子序列,不是子串。

提示:

0 <= s.length <= 5 * 104
s 由英文字母、數字、符號和空格組成
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        slen = len(s)
        if slen == 0:
            return 0
        
        occ = set()
        rt, ans = -1, 0
        for i in range(0, slen):
            if i != 0:
                occ.remove(s[i - 1])
            
            while rt + 1 < slen and s[rt + 1] not in occ:
                occ.add(s[rt + 1])
                rt += 1
            
            ans = max(ans, rt - i + 1)

        return ans

76. 最小覆蓋子串

給你一個字符串 s 、一個字符串 t 。返回 s 中涵蓋 t 所有字符的最小子串。如果 s 中不存在涵蓋 t 所有字符的子串,則返回空字符串 "" 。

注意:

對於 t 中重複字符,我們尋找的子字符串中該字符數量必須不少於 t 中該字符數量。
如果 s 中存在這樣的子串,我們保證它是唯一的答案。

示例 1:

輸入:s = "ADOBECODEBANC", t = "ABC"
輸出:"BANC"
示例 2:

輸入:s = "a", t = "a"
輸出:"a"
示例 3:

輸入: s = "a", t = "aa"
輸出: ""
解釋: t 中兩個字符 'a' 均應包含在 s 的子串中,
因此沒有符合條件的子字符串,返回空字符串。

提示:

1 <= s.length, t.length <= 105
s 和 t 由英文字母組成
class Solution {
public:
    string minWindow(string s, string t) {
        unordered_map<char, int> ori, cnt;
        for (const auto& e : t) {
            ++ori[e];
        }
        int left = 0, right = -1;
        int ansL = -1, ansR = -1;
        int curLen = INT_MAX;
        int slen = s.length(), tlen = t.length();
        auto check = [&]() {
            for (const auto& e : ori) {
                if (cnt[e.first] < e.second) {
                    return false;
                }
            }
            return true;
        };
        while (right < slen)
        {
            if (ori.count(s[++right])) {
                ++cnt[s[right]];
            }
            while (check() && left <= right)
            {
                if (right - left + 1 < curLen) {
                    curLen = right - left + 1;
                    ansL = left; 
                    ansR = right;
                }
                if (ori.count(s[left])) {
                    --cnt[s[left]];
                }
                left++;
            }
        }
        return ansL == -1 ? "" : s.substr(ansL, ansR - ansL + 1);

    }
};
class Solution:
    def minWindow(self, s: str, t: str) -> str:
        ori, cnt = dict(), dict()

        def check():
            for key, value in ori.items():
                if cnt.get(key, 0) < value:
                    return False
            return True
        
        slen, tlen = len(s), len(t)
        if tlen == 1:
            return t if t in s else ""

        for c in t:
            ori[c] = ori.get(c, 0) + 1

        left, right = 0, -1
        cur_len = float('inf')
        ansL, ansR = -1, -1
        while right < slen:
            right += 1
            if right < slen and ori.get(s[right], 0):
                cnt[s[right]] = cnt.get(s[right], 0) + 1
            
            while check() and left <= right:
                if right - left + 1 < cur_len:
                    cur_len = right - left + 1
                    ansL = left
                    ansR = left + cur_len
                
                if ori.get(s[left], 0):
                    cnt[s[left]] = cnt.get(s[left], 0) - 1
                
                left += 1
            
        return "" if ansL == -1 else s[ansL : ansR]

239. 滑動窗口最大值

給你一個整數數組 nums,有一個大小爲 k 的滑動窗口從數組的最左側移動到數組的最右側。你只可以看到在滑動窗口內的 k 個數字。滑動窗口每次只向右移動一位。

返回 滑動窗口中的最大值 。

示例 1:

輸入:nums = [1,3,-1,-3,5,3,6,7], k = 3
輸出:[3,3,5,5,6,7]
解釋:

滑動窗口的位置                最大值
---------------               -----
[1  3  -1] -3  5  3  6  7       3
 1 [3  -1  -3] 5  3  6  7       3
 1  3 [-1  -3  5] 3  6  7       5
 1  3  -1 [-3  5  3] 6  7       5
 1  3  -1  -3 [5  3  6] 7       6
 1  3  -1  -3  5 [3  6  7]      7

示例 2:

輸入:nums = [1], k = 1
輸出:[1]

提示:

1 <= nums.length <= 105
-104 <= nums[i] <= 104
1 <= k <= nums.length
class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        # nlen = len(nums)
        # # if nlen == 1:
        # #     return [nums[0]]
        # if nlen <= k:
        #     return [max(nums)]

        # from collections import deque        
        # que = deque()
        # # 每次堆頂都是當前窗口的最大值的下標
        # for i in range(k):
        #     while que and nums[i] >= nums[que[-1]]:
        #         que.pop()
        #     que.append(i)
        
        # ans = [nums[que[0]]]
        # for i in range(k, nlen):
        #     while que and nums[i] >= nums[que[-1]]:
        #         que.pop()
        #     que.append(i)
        #     while que[0] <= i - k:
        #         que.popleft()
        #     ans.append(nums[que[0]])

        # return ans

        nlen = len(nums)
        if nlen == 1:
            return [nums[0]]
        if nlen <= k:
            return [max(nums)]
        
        que = collections.deque()
        for i in range(k):
            while que and nums[i] >= nums[que[-1]]:
                que.pop()
            que.append(i)
        
        ans = [nums[que[0]]]
        for i in range(k, nlen):
            while que and nums[i] >= nums[que[-1]]:
                que.pop()
            que.append(i)
            while que[0] <= i - k:
                que.popleft()
            ans.append(nums[que[0]])
        
        return ans

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章