LeetCode 每日一题 2023/5/8-2023/5/14

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




5/8 1263. 推箱子

对于位置(i,j)可以使用i*n+j表示
记录箱子位置,人位置以及移动步数(box,per,step)
使用mem[(box,per)]记录该状态是否已考虑
广搜 枚举人下一步移动方向
如果人的位置与箱子位置相同 判断当前状态是否出现
说明箱子朝相同方向做了移动 移动步数+1 将该状态加入队列尾端
如果人的位置与箱子位置不同 判断当前状态是否出现
箱子未做移动 将该状态加入队列前端

def minPushBox(grid):
    """
    :type grid: List[List[str]]
    :rtype: int
    """
    from collections import deque
    n,m = len(grid),len(grid[0])
    def check(i,j):
        return 0<=i<n and 0<=j<m and grid[i][j]!="#"
    steps=[(0,-1),(0,1),(1,0),(-1,0)]
    box,per=0,0
    for i,row in enumerate(grid):
        for j,c in enumerate(row):
            if c=="S":
                per = i*m+j
            elif c=="B":
                box = i*m+j
    l = deque([(box,per,0)])
    mem = [[False]*(n*m) for _ in range(n*m)]
    mem[box][per]=True
    while l:
        b,p,d = l.popleft()
        bi,bj = b//m,b%m
        if grid[bi][bj]=="T":
            return d
        pi,pj = p//m,p%m
        for a,b in steps:
            px,py = pi+a,pj+b
            if not check(px,py):
                continue
            if px==bi and py==bj:
                bx,by = bi+a,bj+b
                if not check(bx,by) or mem[bx*m+by][px*m+py]:
                    continue
                mem[bx*m+by][px*m+py] = True
                l.append((bx*m+by,px*m+py,d+1))
            elif not mem[bi*m+bj][px*m+py]:
                mem[bi*m+bj][px*m+py] = True
                l.appendleft((bi*m+bj,px*m+py,d))
    return -1



5/9 2437. 有效时间的数目

考虑小时有几种情况 分钟有几种情况

def countTime(time):
    """
    :type time: str
    :rtype: int
    """
    left,right=1,1
    if time[0]=="?" and time[1]=="?":
        left = 24
    elif time[0]=="?":
        if int(time[1])<=3:
            left=3
        else:
            left=2
    elif time[1]=="?":
        if time[0]=="2":
            left = 4
        else:
            left = 10
    if time[3]=="?" and time[4]=="?":
        right = 60
    elif time[3]=="?":
        right = 6
    elif time[4]=="?":
        right = 10
    return left*right



5/10 1015. 可被 K 整除的最小整数

当k为2或5的倍数 必定不存在这样的数
从1开始对k取余数 m
m1 = 1%k
m2 = 11%k = (110+1)%k = (m110+1)%k
根据前一个余数m得到当前余数

def smallestRepunitDivByK(k):
    """
    :type k: int
    :rtype: int
    """
    if k%2==0 or k%5==0:
        return -1
    m = 1%k
    ans = 1
    while m!=0:
        m = (m*10+1)%k
        ans+=1
    return ans



5/11 1016. 子串能表示从 1 到 N 数字的二进制串

如果s中能找到所有k长度的2进制串 则必定能够找到(1~k-1)长度的2进制串
所以只需要考虑2^k~n 2(k-1)~2k-1两组情况
如果2^k~n存在 则2^(k-1)~n/2也存在 所以后一组只需要考虑n//2+1~2^k-1

def queryString(s, n):
    """
    :type s: str
    :type n: int
    :rtype: bool
    """
    if n==1:
        return '1' in s
    m = len(s)
    k = n.bit_length()-1
    if m<max(n-(1<<k)+k+1,(1<<(k-1))+k-1):
        return False
    def check(k,minv,maxv):
        if minv>maxv:
            return True
        ss = set()
        mask = (1<<(k-1))-1
        x = int(s[:k-1],2)
        for c in s[k-1:]:
            x = ((x&mask)<<1)|int(c)
            if minv<=x<=maxv:
                ss.add(x)
        return len(ss)==maxv-minv+1
    return check(k,n//2+1,(1<<k)-1) and check(k+1,1<<k,n)



5/12 1330. 翻转子数组得到最大的数组值

参考 https://leetcode.cn/problems/reverse-subarray-to-maximize-array-value/solutions/2266500/bu-hui-hua-jian-qing-kan-zhe-pythonjavac-c2s6/
假设反转的区域头尾为a,[b…,c],d 反转b…c
中间的不会有影响产生影响的是 少了|a-b|,|c-d|
多了|a-c|,|b-d|
diff = |a-c|+|b-d|-|a-b|-|c-d|
经过分析可以得到 diff=2min(c,d)-2max(a,b)>=0
遍历相邻元素x,y维护min(x,y)的最大值maxv max(x,y)的最小值minv
如果maxv>minv 有diff=2*(maxv-minv)

def maxValueAfterReverse(nums):
    """
    :type nums: List[int]
    :rtype: int
    """
    base = 0
    diff = 0
    maxv,minv=float("-inf"),float("inf")
    for i in range(len(nums)-1):
        x,y=nums[i],nums[i+1]
        base += abs(x-y)
        maxv = max(maxv,min(x,y))
        minv = min(minv,max(x,y))
        diff = max(diff,abs(nums[0]-y)-abs(x-y),abs(nums[-1]-x)-abs(x-y))
    return base+max(diff,2*(maxv-minv))



5/13 2441. 与对应负数同时存在的最大正整数

从小到大排序 左右双指针

def findMaxK(nums):
    """
    :type nums: List[int]
    :rtype: int
    """
    nums.sort()
    l,r=0,len(nums)-1
    while l<r:
        if nums[l]>0 or nums[r]<0:
            return -1
        if -nums[l]==nums[r]:
            return nums[r]
        if -nums[l]>nums[r]:
            l+=1
        else:
            r-=1
    return -1



5/14 1054. 距离相等的条形码

统计每个数出现次数 按次数从大到小排序
建立答案数组 安排好的次序放入数组偶数下标 放完后从头放入奇数下标

def rearrangeBarcodes(barcodes):
    """
    :type barcodes: List[int]
    :rtype: List[int]
    """
    from collections import Counter
    n = len(barcodes)
    cnt = Counter(barcodes)
    barcodes.sort(key=lambda x:(-cnt[x],x))
    ans = [0]*n
    ans[::2]=barcodes[:(n+1)//2]
    ans[1::2] = barcodes[(n+1)//2:]
    return ans



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值