我的代码为什么出现了TLE,而类似的实现通过了(BFS)?

huangapple go评论70阅读模式
英文:

Why my code is giving TLE while a similar implementation passes (BFS)?

问题

I am solving this question. I am implementing BFS, and my implementation is as follows:

class Solution:
    def shortestPathBinaryMatrix(self, grid: List[List[int]]) -> int:

        if grid[0][0] == 1:
            return -1
        M=len(grid)-1
        seen = set()
        q = deque([])
        res = float('inf')
        q.append((0,0,1))

        while q:
            r,c, curr = q.popleft()
            if r==M and c==M:
                return curr
            directions = [[1,0], [0,1], [1,1], [-1,0], [0,-1], [-1,-1], [1, -1], [-1, 1]]
            seen.add((r,c))
            for ro, co in directions:
                nr, nc = r+ro, c+co
                if (nr,nc) in seen or nr < 0 or nc < 0 or nr > M or nc > M or grid[nr][nc] == 1:
                    continue
                q.append((nr,nc,curr+1))
        return -1

but this gives TLE for large input. However, a similar implementation passes:

class Solution:
    def shortestPathBinaryMatrix(self, grid: List[List[int]]) -> int:
        N = len(grid)
        q = deque([(0, 0, 1)]) # r, c, length
        visit = set((0, 0))
        direct = [[0, 1], [1, 0], [0, -1], [-1, 0],
                  [1, 1], [-1, -1], [1, -1], [-1, 1]]
        while q:
            r, c, length = q.popleft()
            if (min(r, c) < 0 or max(r, c) >= N or grid[r][c]):
                continue
            if r == N - 1 and c == N - 1:
                return length
            for dr, dc in direct:
                if (r + dr, c + dc) not in visit:
                    q.append((r + dr, c + dc, length + 1))
                    visit add((r + dr, c + dc))
        return -1

What is slowing my code down?

I am unable to understand why my code is slower.

英文:

I am solving this question. I am implementing BFS and my implementation is as follows:

class Solution:
    def shortestPathBinaryMatrix(self, grid: List[List[int]]) -&gt; int:

        if grid[0][0] == 1:
            return -1
        M=len(grid)-1
        seen = set()
        q = deque([])
        res = float(&#39;inf&#39;)
        q.append((0,0,1))

        while q:
            r,c, curr = q.popleft()
            if r==M and c==M:
                return curr
            directions = [[1,0], [0,1], [1,1], [-1,0], [0,-1], [-1,-1], [1, -1], [-1, 1]]
            seen.add((r,c))
            for ro, co in directions:
                nr, nc = r+ro, c+co
                if (nr,nc) in seen or nr &lt; 0 or nc &lt; 0 or nr &gt; M or nc &gt; M or grid[nr][nc] == 1:
                    continue
                q.append((nr,nc,curr+1))
        return -1

but this gives TLE for large input. However, a similar implementation passes:

class Solution:
    def shortestPathBinaryMatrix(self, grid: List[List[int]]) -&gt; int:
        N = len(grid)
        q = deque([(0, 0, 1)]) # r, c, length
        visit = set((0, 0))
        direct = [[0, 1], [1, 0], [0, -1], [-1, 0],
                  [1, 1], [-1, -1], [1, -1], [-1, 1]]
        while q:
            r, c, length = q.popleft()
            if (min(r, c) &lt; 0 or max(r, c) &gt;= N or
                grid[r][c]):
                continue
            if r == N - 1 and c == N - 1:
                return length
            for dr, dc in direct:
                if (r + dr, c + dc) not in visit:
                    q.append((r + dr, c + dc, length + 1))
                    visit.add((r + dr, c + dc))
        return -1

What is slowing my code down?

I am unable to understand why my code is slower.

答案1

得分: 1

您的解决方案只需进行两个小的更改就能通过。

主要更改在于将将已访问的单元格添加到 seen 的代码移到了与新单元格添加到队列的代码相同的级别。

原始代码的缺点是,当重复的单元格在相同的BFS级别上添加到队列时,它无法避免重复,因为 seen 不会随着队列的更新而更新。

seen 的更新移到与队列的更新在同一级别上确保了仅有独特的单元格会被添加到下一级BFS的队列中。

英文:

You solution would pass with just two small changes.

class Solution:
    def shortestPathBinaryMatrix(self, grid: List[List[int]]) -&gt; int:

        if grid[0][0] == 1:
            return -1
        M=len(grid)-1
        seen = set([(0,0)])  # &lt;-- initialize with (0, 0)
        q = deque([])
        res = float(&#39;inf&#39;)
        q.append((0,0,1))

        while q:
            r,c, curr = q.popleft()
            if r==M and c==M:
                return curr
            directions = [[1,0], [0,1], [1,1], [-1,0], [0,-1], [-1,-1], [1, -1], [-1, 1]]
            
            for ro, co in directions:
                nr, nc = r+ro, c+co
                if (nr,nc) in seen or nr &lt; 0 or nc &lt; 0 or nr &gt; M or nc &gt; M or grid[nr][nc] == 1:
                    continue
                q.append((nr,nc,curr+1))
                seen.add((nr,nc))  # &lt;-- mark nodes that surely will be visited
        return -1

Note that the main change in the logic is that the line to add visited cells to seen is moved to the same level where new cells are added to the queue.

The drawback of the original code is that it cannot avoid duplication when duplicated cells are added to the queue on the same BFS level, because seen is not updated along with the queue.

Moving the update of seen to the same level as the update of queue guarantees that only unique cells are added to the queue for the next level of BFS.

huangapple
  • 本文由 发表于 2023年3月4日 02:18:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/75630579.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定