2022-01-12 每日打卡:难题精刷
写在前面
“这些事儿在熟练之后,也许就像喝口水一样平淡,但却能给初学者带来巨大的快乐,我一直觉得,能否始终保持如初学者般的热情、专注,决定了在做某件事时能走多远,能做多好。” 该系列文章由python编写,所刷题目共三个来源:之前没做出来的 ;Leetcode中等,困难难度题目; 周赛题目;某个专题的经典题目,所有代码已AC。每日1-3道,随缘剖析,希望风雨无阻,作为勉励自己坚持刷题的记录。
剑指 Offer II 017. 含有所有字符的最短字符串
从暴力循环->滑动窗口:
class Solution:
def minWindow(self, s: str, t: str) -> str:
j, res = 0, ''
t = Counter(t)
c = Counter()
for i in range(len(s)):
# 只统计满足条件(t中)的字符
if s[i] in t:
c[s[i]] += 1
# 只要没全部出现,就需要继续统计
# 全部出现后,控制左边界
while j <= i and not t-c:
if not res or len(res) > i-j+1:
res = s[j:i+1]
# 控制左边界,直到出现t中字符
if s[j] in c:
c[s[j]] -= 1
j += 1
return res
剑指 Offer II 039. 直方图最大矩形面积
单调栈,最大矩形的面积一定存在于:左右两侧比该柱子矮的两个柱子的坐标之间(最近的),面积为两侧矮柱子之间的宽度乘以该柱子的高度。
保证栈中柱子是递增的,因为递增的柱子的面积一定可以扩展下去。而每次遇到矮柱子,将计算面积并更新,直到最后。
class Solution:
def largestRectangleArea(self, heights: List[int]) -> int:
# 对于最后保持递增的柱子,需要一个结束条件
heights.append(0)
stack = [[0,-1]]
maxn = 0
for i in range(len(heights)):
while stack and stack[-1][0]>heights[i]:
h, index = stack.pop()
maxn = max(h*(i - stack[-1][1]-1), maxn)
stack.append([heights[i], i])
return maxn
剑指 Offer II 117. 相似的字符串
- 图dfs:
class Solution:
def numSimilarGroups(self, A: List[str]) -> int:
n = len(A)
w = len(A[0])
s = set(A)
def swap(i, j):
cnt = 0
for a, b in zip(i, j):
if a != b:
cnt += 1
if cnt > 2:
return False
return True
ans = 0
while s:
for c in s.copy():
queue = [c]
visited = {c}
s.discard(c)
idx = 0
while idx < len(queue):
first = queue[idx]
for n in s.copy():
if swap(first, n):
queue.append(n)
visited.add(n)
s.discard(n)
idx += 1
ans += 1
break
return ans
- 并查集(这里按秩并其实是没有必要的):
class UF: #
# 优化版本并查集,优化并查集
def __init__(self, n: int):
self.rank = [1] * n
self.f = list(range(n))
def find(self, x: int) -> int:
if self.f[x] == x:
return x
self.f[x] = self.find(self.f[x])
return self.f[x]
def union(self, x: int, y: int):
fx, fy = self.find(x), self.find(y)
if fx == fy:
return
# 都往同一个方向并,同时统计个数
if self.rank[fx] < self.rank[fy]:
fx, fy = fy, fx
self.rank[fx] += self.rank[fy]
self.f[fy] = fx
class Solution:
def numSimilarGroups(self, strs: List[str]) -> int:
# 已知所有词是异位词
def judge(w1,w2):
diff = 0
for i in range(len(w1)):
if w1[i] != w2[i]:
diff += 1
if diff >= 3:
return False
return True
n = len(strs)
ufSet = UF(n)
countSet = set()
for i in range(n):
for j in range(i+1,n):
if judge(strs[i],strs[j]):
ufSet.union(i,j)
for i in range(n):
countSet.add(ufSet.find(i))
return len(countSet)