LeetCode 每日一题 2022/6/6-2022/6/12

记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步




6/6 732. 我的日程安排表 III

将每个日程看作一条线段 求每个时间点上最多有几个日程
1.差分数组
日程起始处+1 日程结束处-1 从头遍历 每经过一个时间点
求当前拥有日程的最大值
2.线段树
动态开点+懒标记模板

class MyCalendarThree1(object):

    def __init__(self):
        self.m = {}


    def book(self, start, end):
        """
        :type start: int
        :type end: int
        :rtype: int
        """
        self.m[start] = self.m.get(start,0)+1
        self.m[end] = self.m.get(end,0)-1
        
        l = sorted(self.m.keys())
        cur = 0
        ans = 0
        for t in l:
            cur += self.m[t]
            ans = max(ans,cur)
        return ans

class Node:
    def __init__(self,l,r):
        self.left = None
        self.right = None
        self.l = l
        self.r = r
        self.mid = (l+r)>>1
        self.v = 0
        self.add = 0
class SegmentTree:
    def __init__(self):
        self.root = Node(1,int(1e9+1))
    def modify(self,l,r,v,node=None):
        if l>r:
            return 
        if not node:
            node = self.root
        if node.l>=l and node.r<=r:
            node.v +=v 
            node.add +=v
            return
        self.pushdown(node)
        if l<=node.mid:
            self.modify(l,r,v,node.left)
        if r>node.mid:
            self.modify(l,r,v,node.right)
        self.pushup(node)
    def pushdown(self,node):
        if not node.left :
            node.left = Node(node.l,node.mid)
        if not node.right:
            node.right = Node(node.mid+1,node.r)
        if node.add:
            node.left.v += node.add
            node.right.v += node.add
            node.left.add += node.add
            node.right.add += node.add
            node.add = 0
    def pushup(self,node):
        node.v = max(node.left.v,node.right.v)
    def query(self,l,r,node=None):
        if l>r:
            return 0
        if not node:
            node = self.root
        if node.l>=l and node.r <=r:
            return node.v
        self.pushdown(node)
        v = 0
        if l<=node.mid:
            v = max(v,self.query(l,r,node.left))
        if r>=node.mid:
            v = max(v,self.query(l,r,node.right))
        return v
        
    
class MyCalendarThree2(object):

    def __init__(self):
        self.tr = SegmentTree()
    
    def book(self, start, end):
        """
        :type start: int
        :type end: int
        :rtype: int
        """
        self.tr.modify(start+1,end,1)
        return self.tr.query(1,int(1e9+1))



6/7 875. 爱吃香蕉的珂珂

check用来检验每小时吃v根是否能够完成
二分法搜索查询最小的v

def minEatingSpeed(piles, h):
    """
    :type piles: List[int]
    :type h: int
    :rtype: int
    """
    piles.sort(reverse=True)
    def check(v):
        num = 0
        for pile in piles:
            num += pile//v
            if pile%v>0:
                num +=1
            if num>h:
                return False
        return num<=h
    
    l,r = 1,max(piles)
    while l<=r:
        mid = (r+l)>>1
        if check(mid):
            r = mid-1
        else:
            l = mid+1
    return l



6/8 1037. 有效的回旋镖

确认不存在相同的点
确认不在一条直线上

def isBoomerang(points):
    """
    :type points: List[List[int]]
    :rtype: bool
    """
    a,b = points[0]
    c,d = points[1]
    e,f = points[2]
    if (a==c and b==d) or (a==e and b==f) or (c==e and d==f):
        return False
    if (d-b)(e-c)==(f-d)(c-a):
        return False
    return True



6/9 497. 非重叠矩形中的随机点

计算每个矩形包含的点的个数
列表l[i]存放前i个矩形点个数和 前缀和
总个数为s
随机在s中取一个整数x
求出得到x需要多少个矩形 并在当前矩形中得到对应点

class Solution(object):
    def __init__(self, rects):
        """
        :type rects: List[List[int]]
        """
        self.rects = rects
        self.s = 0
        self.l = [0]
        for a,b,c,d in rects:
            s = (c-a+1)*(d-b+1)
            self.s +=s
            self.l.append(self.s)


    def pick(self):
        """
        :rtype: List[int]
        """
        import random
        num = random.randint(1,self.s)
        l,r = 0,len(self.l)-1
        while l<=r:
            mid = (l+r)>>1
            if self.l[mid]>=num:
                r = mid-1
            else:
                l = mid+1
        leave = num-self.l[r]-1
        a,b,c,d = self.rects[r]
        w = c-a+1
        y = leave//w
        x = leave%w
        return [a+x,b+y]



6/10 730. 统计不同回文子序列

动态规划
只包含a,b,c,d四种字符
dp[x][i][j] 代表在s[i:j]中以x开头结尾的子序列个数
如果s[i]=x s[j]=x dp[x,i,j] = dp[a,b,c,d][i+1,j-1] + 2 (头尾都加上x,并且多出x,xx两个)
如果s[i]=x s[j]!=x dp[x,i,j] = dp[x,i,j-1]
如果s[i]!=x s[j]=x dp[x,i,j] = dp[x,i+1,j]
如果s[i]!=x s[j]!=x dp[x,i,j] = dp[x,i+1,j-1]
s[i]=x dp[x][i][i]=1
s[i]!=x dp[x][i][i]=0
[i:j]长度从小到大考虑


def countPalindromicSubsequences(s):
    """
    :type s: str
    :rtype: int
    """
    MOD = 10**9+7
    n = len(s)
    dp = [[[0]*n for _ in range(n)] for _ in range(4)]
    for i,c in enumerate(s):
        dp[ord(c)-ord('a')][i][i] = 1
    for l in range(2,n+1):
        for j in range(l-1,n):
            i = j-l+1
            for ind,c in enumerate("abcd"):
                if s[i]==c and s[j]==c:
                    dp[ind][i][j] = (2+ sum(d[i+1][j-1] for d in dp))%MOD
                elif s[i]==c and s[j]!=c:
                    dp[ind][i][j] = dp[ind][i][j-1]
                elif s[i]!=c and s[j]==c:
                    dp[ind][i][j] = dp[ind][i+1][j]
                else:
                    dp[ind][i][j] = dp[ind][i+1][j-1]
    return sum(d[0][n-1]for d in dp)%MOD


6/11 926. 将字符串翻转到单调递增

dp[0][i],dp[1][i]分别记录到i为止以0,1结尾需要反转的次数
dp[0][i] = dp[0][i-1]+(s[i]==0/1)
dp[1][i] = min(dp[0][i-1],dp[1][i-1])+(s[i]==1/0)
即时更新 用dp0,dp1即可

def minFlipsMonoIncr(s):
    """
    :type s: str
    :rtype: int
    """
    dp0,dp1=0,0    
    for c in s:
        cur0,cur1 = dp0,min(dp0,dp1)
        if c=="1":
            cur0+=1
        else:
            cur1+=1
        dp0,dp1=cur0,cur1
    return min(dp0,dp1)
        



6/12 890. 查找和替换模式

使用m记录从pattern中的x对应word中的y的关系
使用used记录word中的字符y是否已经有了对应的x


def findAndReplacePattern(words, pattern):
    """
    :type words: List[str]
    :type pattern: str
    :rtype: List[str]
    """
    def check(word,pattern):
        m = {}
        used = set()
        for i in range(len(word)):
            x,y = pattern[i],word[i]
            if x in m:
                if m[x]!=y:
                    return False
                else:
                    continue
            else:
                if y in used:
                    return False
                m[x]=y
                used.add(y)
                
        return True
    
    ans = []
    for word in words:
        if check(word,pattern):
            ans.append(word)
    return ans


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值