面试题_滑动窗口

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

posted @ 2022-08-04 00:08  douzujun  阅读(45)  评论(0编辑  收藏  举报