我试图用BFS解决leetcode问题https://leetcode.com/problems/open-the-lock/,并提出了以下方法.

def openLock(self, deadends: List[str], target: str): -> int
      def getNeighbors(node) ->List[str]:
            neighbors = []
            dirs = [-1, 1]
            for i in range(len(node)):
                for direction in dirs:
                    x = (int(node[i]) + direction) % 10
                    neighbors.append(node[:i] + str(x) + node[i+1:])
            return neighbors
                        
        start = '0000'
        if start in deadends:
            return -1
        queue = deque()
        queue.append((start, 0))
        turns = 0
        visited = set()
        deadends = set(deadends)
        while queue:
            state, turns = queue.popleft()
            visited.add(state)
            if state == target:
                return turns
            for nb in getNeighbors(state):
                if nb not in visited and nb not in deadends:   
                    queue.append((nb, turns+1))
        return -1

然而,这段代码遇到了一个超过时间限制的异常,它只通过了测试用例的2/48.例如,在一个测试用例中,死区是["8887","8889","8878","8898","8788","8988","7888","9888"],目标是"8888"(开始总是"0000"),我的解决方案是TLE.我注意到,如果我本质上更改了一行并将相邻 node 添加到内部循环中的访问集,那么我的解决方案将通过该测试用例和所有其他测试用例.

for nb in getNeighbors(state):
     if nb not in visited and nb not in deadends:   
         visited.add(nb)
         queue.append((nb, turns+1))

然后,我的while循环变为

while queue:
            state, turns = queue.popleft()
            if state == target:
                return turns
            for nb in getNeighbors(state):
                if nb not in visited and nb not in deadends:   
                    visited.add(nb)
                    queue.append((nb, turns+1))

有人能解释为什么第一种方法会遇到TLE,而第二种方法不会?

推荐答案

对绝对地当项目第一次添加到队列时,而不是从队列中删除时,需要将其添加到visited.否则,您的队列将呈指数级增长.

让我们看看1111.您的代码将向队列中添加twice0、0twice、0010、0001(和其他).然后,您的代码将分别添加1twice、1010、twice1、0110、0101、0011和其他twice个元素,因为它们是队列中两个元素的邻居,并且尚未被访问.然后把11101010110110111加四次.相反,如果您正在搜索5555,您的队列中将有许多重复项.

visited变量的名称更改为seen.请注意,项目一旦被放入队列,就不再需要再放入队列.

说真的,试着搜索没有死胡同的5555.当你找到它时,看看队列,看看队列上有多少个元素,而不是队列上有多少distinct个元素.

Python相关问答推荐

将输入管道传输到正在运行的Python脚本中

用Python解密Java加密文件

从groupby执行计算后创建新的子框架

无法使用DBFS File API路径附加到CSV In Datricks(OSError Errno 95操作不支持)

为一个组的每个子组绘制,

与命令行相比,相同的Python代码在Companyter Notebook中运行速度慢20倍

在matplotlib中删除子图之间的间隙_mosaic

Flash只从html表单中获取一个值

基于Scipy插值法的三次样条系数

为什么在FastAPI中创建与数据库的连接时需要使用生成器?

如何在Python请求中组合多个适配器?

30个非DATETIME天内的累计金额

不允许 Select 北极滚动?

为什么t sns.barplot图例不显示所有值?'

Python将一个列值分割成多个列,并保持其余列相同

用fft计算指数复和代替求和来模拟衍射?

Polars表达式无法访问中间列创建表达式

如何在Polars中创建条件增量列?

极地数据帧:ROLING_SUM向前看

在Python Polar中从一个函数调用添加多个列