IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> Python广度优先遍历BFS中使用list.pop(0)超过时间限制的解决办法 -> 正文阅读

[数据结构与算法]Python广度优先遍历BFS中使用list.pop(0)超过时间限制的解决办法

楼主遇到这个问题是在LeetCode刷题时遇到2039. 网络空闲的时刻这个题目,按照BFS模板写的最后一个测试案例怎么都过不去(甚至复制官方的都过不去),幸得高人指点才发现问题所在。
题目描述:
在这里插入图片描述

我原始的代码为:

class Solution:
    def networkBecomesIdle(self, edges: List[List[int]], patience: List[int]) -> int:
        n = len(patience)
        graph = [[] for _ in range(n)]
        for x, y in edges:
            graph[x].append(y)
            graph[y].append(x)
        
        # 广度优先遍历
        queue = [0] 
        distance = [-1 for _ in range(n)] #得到每一个节点到0节点的最短距离
        visited = [False] * n
        visited[0] = True
        dis_cur = 0
        while queue:
            size = len(queue)
            for _ in range(size):
                node = queue.pop(0)
                distance[node] = dis_cur
                for adj in graph[node]:
                    if visited[adj] == False:
                        queue.append(adj)
                        visited[adj] = True
            dis_cur += 1
        
        #遍历每个节点计算其变成空闲状态的最晚时间
        res = 0
        for i in range(1,n):
            time = patience[i] * ((2*distance[i] - 1) // patience[i]) + 2 * distance[i] + 1
            res = max(res,time)
        return res 

这里会超出时间限制的原因是:使用list.pop(0)的时间复杂度为O(n),在BFS那块达到了 O ( n 2 ) O(n^2) O(n2),所以在面对 1 0 5 10^5 105数据大小时会超出时间限制。

解决方法有两个:

  1. 使用两个list来回倒
  2. 使用Python库自带的双端队列collections.deque()

需要说明的是list是一张顺序表,在使用list.pop(0)时需要使所有的元素向前平移,时间复杂度为O(n),而deque是链表,在头部插入或删除节点时间复杂度为O(1)。

先说方法一,使用两个list来回替换代替了queue.pop(0),避免了一次多余的循环:
该部分代码来自LeetCode用户Meteordream对我的评论,感谢大佬!

class Solution:
    def networkBecomesIdle(self, edges: List[List[int]], patience: List[int]) -> int:
        n = len(patience)
        graph = [[] for _ in range(n)]
        for x, y in edges:
            graph[x].append(y)
            graph[y].append(x)
        
        # 广度优先遍历
        queue = [0] 
        distance = [-1 for _ in range(n)] #得到每一个节点到0节点的最短距离
        visited = [False] * n
        visited[0] = True
        dis_cur = 0
        while queue:
            # 这里用另外一个list
            tmp = list()
            # 不要 pop 了,直接遍历,新加入的放到新list
            for node in queue:
                distance[node] = dis_cur
                for adj in graph[node]:
                    if visited[adj] == False:
                        tmp.append(adj)
                        visited[adj] = True
            dis_cur += 1
            # 新 list 换掉旧 queue
            queue = tmp
        
        #遍历每个节点计算其变成空闲状态的最晚时间
        res = 0
        for i in range(1,n):
            time = patience[i] * ((2*distance[i] - 1) // patience[i]) + 2 * distance[i] + 1
            res = max(res,time)
        return res

方法二:
使用Python自带的双端队列方法

class Solution:
    def networkBecomesIdle(self, edges: List[List[int]], patience: List[int]) -> int:
        n = len(patience)
        graph = [[] for _ in range(n)]
        for x, y in edges:
            graph[x].append(y)
            graph[y].append(x)
        
        # 广度优先遍历
        queue = collections.deque() #替换为双端队列
        queue.append(0)
        distance = [-1 for _ in range(n)] #得到每一个节点到0节点的最短距离
        visited = [False] * n
        visited[0] = True
        dis_cur = 0
        while queue:
            for _ in range(len(queue)):
                node = queue.popleft()
                distance[node] = dis_cur
                for adj in graph[node]:
                    if visited[adj] == False:
                        queue.append(adj)
                        visited[adj] = True
            dis_cur += 1

        
        #遍历每个节点计算其变成空闲状态的最晚时间
        res = 0
        for i in range(1,n):
            time = patience[i] * ((2*distance[i] - 1) // patience[i]) + 2 * distance[i] + 1
            res = max(res,time)
        return res
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-03-21 21:17:10  更:2022-03-21 21:20:34 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 11:30:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码