問題は、グリッドが与えられた0点の場合、すべての建物までの最短距離を見つけることです。あなたは上、下、左、右に移動することだけが許可されています。あなたは次の値に遭遇することができます。すべての建物との最短距離を求める最適化アルゴリズム
0 - 空のスペース 1 - 建物 2 - 障害物
Pythonで書かれた私のソリューションは以下の通りです:
import sys
class Solution(object):
def shortestDistance(self, grid):
"""
:type grid: List[List[int]]
:rtype: int
"""
if grid is None:
return -1
tup = self.findPoints(grid)
buildings = tup[0]
zeroPoints = tup[1]
distances = []
for points in zeroPoints:
dist = self.bfs(grid, points, buildings)
distances += [dist]
return self.select(distances)
def findPoints(self, grid):
buildings = 0
zeroPoints = []
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j] == 0:
zeroPoints += [[i,j]]
elif grid[i][j] == 1:
buildings += 1
return (buildings, zeroPoints)
def bfs(self, grid, root, targets):
hits, sumDist = 0, 0
targetsFound = []
while hits < targets:
q = []
q.append((root, 0))
found = False
visited = []
while(len(q) > 0):
tup = q.pop(0)
curr = tup[0]
dist = tup[1]
if grid[curr[0]][curr[1]] == 1 and curr not in targetsFound:
found = True
sumDist += dist
targetsFound += [curr]
break
if grid[curr[0]][curr[1]] == 0:
if (curr[0] - 1) >= 0 and grid[curr[0] -1][curr[1]] != 2 and [curr[0] - 1, curr[1]] not in visited:
q.append(([curr[0] - 1, curr[1]], dist + 1))
visited += [[curr[0] - 1, curr[1]]]
if (curr[0] + 1) < len(grid) and grid[curr[0] + 1][curr[1]] != 2 and [curr[0] + 1, curr[1]] not in visited:
q.append(([curr[0] + 1, curr[1]], dist + 1))
visited += [[curr[0] + 1, curr[1]]]
if (curr[1] - 1) >= 0 and grid[curr[0]][curr[1] - 1] != 2 and [curr[0], curr[1] - 1] not in visited:
q.append(([curr[0], curr[1] - 1], dist + 1))
visited += [[curr[0], curr[1] - 1]]
if (curr[1] + 1) < len(grid[0]) and grid[curr[0]][curr[1] + 1] != 2 and [curr[0], curr[1] + 1] not in visited:
q.append(([curr[0], curr[1] + 1], dist +1))
visited += [[curr[0], curr[1] + 1]]
if found:
hits += 1
else:
return - 1
return sumDist
def select(self, distances):
min = sys.maxsize
for dist in distances:
if dist < min and dist != -1:
min = dist
if min == sys.maxsize:
return -1
else:
return min
私の質問は:
ソリューションの効率をどのように高めることができますか?今、私は、次の入力にLeetcode上の制限時間を超えていますが、それは他のすべてのテスト入力のために正しいです:
[[2,0,0,2,0,0,0,0,0,2,2,0,0,0,0,0,0,0,0,0,1,2,0,2,0,1,1,0],[0,1,0,1,1,2,0,0,2,0,0,2,0,2,2,0,2,0,2,0,0,0,0,0,0,0,0,0],[1,0,0,1,2,0,0,2,0,2,0,0,0,0,0,0,0,0,0,2,0,2,0,0,0,0,0,2],[0,0,2,2,2,1,0,0,2,0,0,0,0,0,0,0,0,0,2,2,2,2,1,0,0,0,0,0],[0,2,0,2,2,2,2,1,0,0,0,0,1,0,2,0,0,0,0,2,2,0,0,0,0,2,2,1],[0,0,2,1,2,0,2,0,0,0,2,2,0,2,0,2,2,2,2,2,0,0,0,0,2,0,2,0],[0,0,0,2,1,2,0,0,2,2,2,1,0,0,0,2,0,2,0,0,0,0,2,2,0,0,1,1],[0,0,0,2,2,0,0,2,2,0,0,0,2,0,2,2,0,0,0,2,2,0,0,0,0,2,0,0],[2,0,2,0,0,0,2,0,2,2,0,2,0,0,2,0,0,2,1,0,0,0,2,2,0,0,0,0],[0,0,0,0,0,2,0,2,2,2,0,0,0,0,0,0,2,1,0,2,0,0,2,2,0,0,2,2]]
注:変更訪れ、targetsFoundは、効率を上げますが、すべてのテストケースに合格するのに十分ではありません。
更新:
各建物の代わりに、それぞれゼロ点から検索するためのアルゴリズムを変更することにより、私は、特定の大入力に96%によって、アルゴリズムを改善し、すべてのテストケースを通過することができました。更新されたアルゴリズムは以下の通りです。彼の提案に対するネザーランドのおかげです。
def shortestDistanceWalk(grid):
onePoints = findPointsWalk(grid)
for point in onePoints:
bfsWalk(grid, point)
shortestDistance = sys.maxsize
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j] < 0 and shortestDistance > (grid[i][j] * -1):
shortestDistance = (grid[i][j] * -1)
if shortestDistance == sys.maxsize:
return -1
else:
return shortestDistance
def findPointsWalk(grid):
onePoints = []
for i in range(len(grid)):
for j in range(len(grid[0])):
if grid[i][j] == 1:
onePoints += [[i,j]]
return onePoints
def bfsWalk(grid, root):
q = []
q.append((root, 0))
found = False
visited = set()
while(len(q) > 0):
tup = q.pop(0)
curr = tup[0]
dist = tup[1]
if grid[curr[0]][curr[1]] <= 0:
grid[curr[0]][curr[1]] += dist
if (curr[0] - 1) >= 0 and grid[curr[0] -1][curr[1]] <= 0 and (curr[0] - 1, curr[1]) not in visited:
q.append(([curr[0] - 1, curr[1]], dist - 1))
visited.add((curr[0] - 1, curr[1]))
if (curr[0] + 1) < len(grid) and grid[curr[0] + 1][curr[1]] <= 0 and (curr[0] + 1, curr[1]) not in visited:
q.append(([curr[0] + 1, curr[1]], dist - 1))
visited.add((curr[0] + 1, curr[1]))
if (curr[1] - 1) >= 0 and grid[curr[0]][curr[1] - 1] <= 0 and (curr[0], curr[1] - 1) not in visited:
q.append(([curr[0], curr[1] - 1], dist - 1))
visited.add((curr[0], curr[1] - 1))
if (curr[1] + 1) < len(grid[0]) and grid[curr[0]][curr[1] + 1] <= 0 and (curr[0], curr[1] + 1) not in visited:
q.append(([curr[0], curr[1] + 1], dist - 1))
visited.add((curr[0], curr[1] + 1))
for i in range(len(grid)):
for j in range(len(grid[0])):
if (i, j) not in visited:
grid[i][j] = 3
return
感謝を。あなたはより強力な剪定を考えることができますか? –
私はあなたのアプローチが悪いかもしれないと思う、あなたは999のゼロ点と1つの建物を持っていたと想像してください、あなたは999のBFSをします。 その場合、ビルディングから1つのBFSを実行すると、すべてのゼロ点からそれまでの最短経路が見つかるはずであり、999倍効率的になります。 あなたは何とか建物の数/ゼロ点を比較し、場合によってはBFSを実行するフリップを比較したいかもしれません。ちょうどアイデア、それが動作するかどうかは分かりません。 – Nether
私はあなたが正しいと思います。私がそれをする前に、アルゴリズムを変更して各建物から検索し、各ゼロの距離を最も負に更新します。その後、k建物の検索後に最小の負の距離を返し、すべての建物に到達できないポイントで3を格納します。 –