题目
思路
阅读完题干后可以发现需要侧跳的时机是下一个点有障碍,且障碍处在青蛙当前所在跑道。在做周赛时我是先考虑了特殊情况,即当前青蛙所在点的另外的跑道也有障碍,这种情况下青蛙只有唯一的侧跳选择(因为有两条跑道都被封住了)。而如果青蛙所在点所有跑道都没有障碍,那青蛙当前就有两条跑道可以选择。这时可以用贪心的想法,对于待选的两条跑道,分别查找它们下一个最近障碍所在地点,然后选择其中较大者,即保证青蛙在尽量大的距离内不做侧跳调整。在查找下一个最近障碍所在地点时,我是先保存每个跑道障碍出现的地点,然后在出现上述情况以当前位置为起点,二分查找最近障碍点。如果未找到该点,说明后面都是通畅的,这里我是用正无穷表示的(其实这里可以直接返回了,但是竞赛的时候没考虑到这一点)。这里我是遍历数组解决的,时间复杂度为O()。
代码
class Solution:
def minSideJumps(self, obstacles: List[int]) -> int:
n=len(obstacles)
s=2
ans=0
q1=[]
q2=[]
q3=[]
for i in range(n):
if obstacles[i]==1:
q1.append(i)
elif obstacles[i]==2:
q2.append(i)
elif obstacles[i]==3:
q3.append(i)
#print(q1,q2,q3)
def search(s,flag):
nonlocal q1,q2,q3
l=0
if flag==1:
if not q1:
return float('inf')
r=len(q1)-1
res=r
while l<=r:
mid=(l+r)>>1
if q1[mid]<=s:
l=mid+1
else:
res=mid
r=mid-1
#print('res',res)
#print()
# if res>=len(q1):
# return float('inf')
if q1[res]<=s: #这种情况即数组中所有障碍都在起始点之前,表示后面通畅,可以用正无穷表示这种情况
return float('inf')
else:
return q1[res]
elif flag==2:
if not q2:
return float('inf')
r=len(q2)-1
res=r
while l<=r:
mid=(l+r)>>1
if q2[mid]<=s:
l=mid+1
else:
res=mid
r=mid-1
if q2[res]<=s:
return float('inf')
else:
return q2[res]
else:
if not q3:
return float('inf')
r=len(q3)-1
res=r
while l<=r:
mid=(l+r)>>1
if q3[mid]<=s:
l=mid+1
else:
res=mid
r=mid-1
if q3[res]<=s:
return float('inf')
else:
return q3[res]
for i in range(n-1):
#print(i,s,ans)
if obstacles[i+1]==s:
if obstacles[i]==1:
if s==2:
s=3
else:
s=2
elif obstacles[i]==2:
if s==1:
s=3
else:
s=1
elif obstacles[i]==3:
if s==2:
s=1
else:
s=2
else:
if s==1:
temp1=search(i+1,2)
temp2=search(i+1,3)
if temp1<temp2:
s=3
else:
s=2
elif s==2:
temp1=search(i+1,1)
temp3=search(i+1,3)
#print(temp1,temp3)
if temp1<temp3:
s=3
else:
s=1
elif s==3:
temp1=search(i+1,1)
temp2=search(i+1,2)
if temp1<temp2:
s=2
else:
s=1
ans+=1
return ans