LeetCode 每日一题 2022/11/21-2022/11/27

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




11/21 808. 分汤

可以将25ml看作1份 四种情况分别为
A 4 B 0
A 3 B 1
A 2 B 2
A 1 B 3
开始时 A,B拥有的份数一样
当n过大时 A被取完的概率接近于1 误差小于10^-5
假设dp[i][j] 为A剩余i份 B剩余j份时 需要求的概率
dp[i][j] = (dp[i-4][j]+dp[i-3][j-1]+dp[i-2][j-2]+dp[i-1][j-3])/4
当j=0,i>0时 dp[i][j] = 0
当i=0,j>0时 dp[i][j] = 1
当i=0,j=0时 dp[i][j] = 0.5

def soupServings(n):
    """
    :type n: int
    :rtype: float
    """
    n = (n+24)//25
    if n>=179:
        return 1
    dp = [[0]*(n+1) for _ in range(n+1)]
    dp[0] = [0.5]+[1.0]*n
    for i in range(1,n+1):
        for j in range(1,n+1):
            dp[i][j] = (dp[max(0, i - 4)][j] + 
                          dp[max(0, i - 3)][max(0, j - 1)] +
                            dp[max(0, i - 2)][max(0, j - 2)] + 
                                dp[max(0, i - 1)][max(0, j - 3)])/4
    return dp[n][n]



11/22 878. 第 N 个神奇数字

f(x)表示小于等于x内的神奇数字数目 c为a,b最小公倍数lcm
f(x)=x//a+x//b-x//c
f(x)随x增加单调不减 所以可以二分查找第n个神奇数字

def nthMagicalNumber(n, a, b):
    """
    :type n: int
    :type a: int
    :type b: int
    :rtype: int
    """
    def lcm(a,b):
        x,y = a,b
        if a<b:
            x,y = b,a
        while y>0:
            x,y = y,x%y
        return a*b/x
    MOD = 10**9+7
    l,r = min(a,b),min(a,b)*n
    c = lcm(a,b)
    while l<=r:
        mid = (l+r)>>1
        s = mid//a+mid//b-mid//c
        if s>=n:
            r = mid-1
        else:
            l = mid+1
    return (r+1)%MOD



11/23 1742. 盒子中小球的最大数量

用map存储每个盒子内的小球数

def countBalls(lowLimit, highLimit):
    """
    :type lowLimit: int
    :type highLimit: int
    :rtype: int
    """
    def func(x):
        tag = 0
        while x>0:
            tag += x%10
            x = x//10
        return tag
    dic = {}
    ans = 0
    for i in range(lowLimit,highLimit+1):
        tag = func(i)
        dic[tag] = dic.get(tag,0)+1
        if dic[tag]>ans:
            ans = dic[tag]
    return ans



11/24 795. 区间子数组个数

子数组最大值不能大于right 且范围内至少有一个处于[left,right]间
l表示上次出现大于right的位置
r表示上次出现left,right之间的位置
对于当前位置i 可以有r-l个选择
遍历每一个位置可以得到答案

def numSubarrayBoundedMax(nums, left, right):
    """
    :type nums: List[int]
    :type left: int
    :type right: int
    :rtype: int
    """
    ans = 0
    l,r = -1,-1
    for i,num in enumerate(nums):
        if left<=num<=right:
            r = i
        elif num>right:
            l = i
            r = -1
        if r!=-1:
            ans += r-l
    return ans



11/25 809. 情感丰富的文字

func 将字符串中连续相同的字母压缩成一个字母+出现的次数
比较原始s和需要比较的字符串w 压缩后的状态
需要满足 长度相等 每个位置上的字母需要一样
出现的次数 s和w相同 或者s>w 并且s的次数大于等于3

def expressiveWords(s, words):
    """
    :type s: str
    :type words: List[str]
    :rtype: int
    """
    def func(s):
        l = []
        cur = ""
        num = 0
        for c in s:
            if cur=="":
                cur = c
                num=1
            elif cur==c:
                num+=1
            else:
                l.append((cur,num))
                cur = c
                num = 1
        l.append((cur,num))
        return l
    sl = func(s)
    ans = 0
    for w in words:
        wl = func(w)
        if len(wl)!=len(sl):
            continue
        tag = True
        for i in range(len(sl)):
            if sl[i][0]!=wl[i][0]:
                tag = False
                break
            if wl[i][1]==sl[i][1] or (sl[i][1]>wl[i][1] and sl[i][1]>=3):
                continue
            else:
                tag = False
                break
        if tag:
            ans+=1
    return ans



11/26 882. 细分图中的可到达节点

原始节点间的细分节点数可看做节点间的距离
使用dijkstra 可以算出起点到个点的最短路径 记录可达的原始节点数
哈希表used[(u,v)]记录节点u到v可达的细分节点 (v,u)记录v到u可达的细分节点
最后统计时相加 并不大于u,v间的细分节点总数

def reachableNodes(edges, maxMoves, n):
    """
    :type edges: List[List[int]]
    :type maxMoves: int
    :type n: int
    :rtype: int
    """
    import heapq
    from collections import defaultdict
    l = defaultdict(list)
    for u,v,n in edges:
        l[u].append([v,n])
        l[v].append([u,n])
    used = {}
    visited = set()
    ans = 0
    pq = [(0,0)]
    heapq.heapify(pq)
    while pq and pq[0][0]<=maxMoves:
        step,u = heapq.heappop(pq)
        if u in visited:
            continue
        visited.add(u)
        ans +=1
        for v,nodes in l[u]:
            if nodes+step+1<=maxMoves and v not in visited:
                heapq.heappush(pq,[nodes+step+1,v])
            used[(u,v)] = min(nodes,maxMoves-step)
    for u,v,n in edges:
        ans += min(n,used.get((u,v),0)+used.get((v,u),0))
    return ans



11/27 1752. 检查数组是否经排序和轮转得到

原数组所有元素非递减排列
假设轮转x个位置
source[x,…,n-1]+source[0,…,x-1] = nums
找到nums[i-1]<nums[i]
检查0~i-1 i~n-1是否都非递减

def check(nums):
    """
    :type nums: List[int]
    :rtype: bool
    """
    n= len(nums)
    x = 0
    for i in range(1,n):
        if nums[i]<nums[i-1]:
            x=i
            break
    if x==0:
        return True
    for i in range(x+1,n):
        if nums[i]<nums[i-1]:
            return False
    return nums[0]>=nums[-1]



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值