记录了初步解题思路 以及本地实现代码;并不一定为最优 也希望大家能一起探讨 一起进步
目录
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