2022-01-12 每日打卡:难题精刷

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)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值