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