深度优先搜索|778. 水位上升的泳池中游泳,403. 青蛙过河
778. 水位上升的泳池中游泳
写了一个普通的深度优先搜索,勉强写出来了但是超时了,走了一半的例子,21/43,应该是没问题的但是需要更多的剪枝,看了解析可以用二分法+深度优先搜索。
class Solution:
def swimInWater(self, grid: List[List[int]]) -> int:
n = len(grid)
used = [[False]*n for _ in range(n)]
t = [grid[0][0]]
res = []
def dfs(i,j):
nonlocal t
if i == n-1 and j == n-1:
res.append(t[-1])
return
used[i][j] = True
for k1,k2 in [[i,j+1],[i+1,j],[i,j-1],[i-1,j]]:
if res and t[-1] >= min(res): break
if 0<=k1<n and 0<=k2<n and not used[k1][k2]:
#print(t)
if t[-1] >= grid[k1][k2]:
dfs(k1,k2)
used[k1][k2] = False
else:
t.append(grid[k1][k2])
dfs(k1,k2)
t.pop()
used[k1][k2] = False
dfs(0,0)
#print(res)
return min(res)
二分法+深度优先搜索
首先第一点,初始的时间(水位线)一定是grid[0][0]
和grid[n-1][n-1]
里大的那个,也是节省时间的一步。
第二点就是如果起始时间就可以留到最后一格的,那肯定是最小的,也没必要继续二分了,直接输出。
第三点grid
的最大值是
n
2
−
1
n^2-1
n2−1,也就是说时间是
n
2
n^2
n2肯定能留到最后一格,那么我们就可以以max(grid[0][0]
,grid[n-1][n-1]
)为left,
n
2
−
1
n^2-1
n2−1为right来进行二分法,而这样写的话在dfs里也不用更新时间了,只需要判断能不能走通就行,因为二分的时候就可以判断。
class Solution:
def swimInWater(self, grid: List[List[int]]) -> int:
def dfs(t,i,j,used):
if i == n-1 and j == n-1:
return True
used[i][j] = True
for k1,k2 in [[i,j+1],[i+1,j],[i,j-1],[i-1,j]]:
#这里不用改t了,小了直接就走不通
if 0<=k1<n and 0<=k2<n and not used[k1][k2] and t >= grid[k1][k2]:
#print(t)
if dfs(t,k1,k2,used):
return True
return False
n = len(grid)
left = max(grid[0][0],grid[n-1][n-1])
used = [[False]*n for _ in range(n)]
if dfs(left,0,0,used):
return left
right = n**2 - 1
while left <= right:
mid = (left + right) // 2
used = [[False]*n for _ in range(n)]
if dfs(mid,0,0,used):
right = mid - 1
else:
left = mid + 1
return left
403. 青蛙过河
写了一个dfs,然后超时了,但是走了十多个了,写法应该没问题
class Solution:
def canCross(self, stones: List[int]) -> bool:
jump = []
if stones[1]-stones[0] != 1:
return False
else:
jump.append(stones[0])
def dfs(i,jump):
if i == stones[-1]:
return True
jump.append(i)
st = jump[-1] - jump[-2]
for k in [st,st+1,st-1]:
if k > 0 and k+i in stones:
if dfs(k+i,jump):
return True
#jump.pop()
return False
return dfs(stones[1],jump)
如果不要jump.pop()
的话,就能到44/53,但是会出错,现在还不是很理解为啥44了才出问题。
开个作弊器把,想不出来了。
class Solution:
def canCross(self, stones: List[int]) -> bool:
if stones[1]-stones[0] != 1:
return False
@functools.lru_cache(None)
def dfs(i,step):
if i == stones[-1]:
return True
for k in [step+1,step-1,step]:
if k > 0 and k+i in stones:
if dfs(k+i,k):
return True
return False
return dfs(stones[1],stones[1]-stones[0])