leetcode 133. clone-graph 克隆图 python3

时间:2020-7-19

题目地址:https://leetcode-cn.com/problems/clone-graph/

题目难度:Medium

题目描述:

给你无向 连通 图中一个节点的引用,请你返回该图的 深拷贝(克隆)。

图中的每个节点都包含它的值 val(int) 和其邻居的列表(list[Node])。

class Node {
    public int val;
    public List<Node> neighbors;
}

测试用例格式:

简单起见,每个节点的值都和它的索引相同。例如,第一个节点值为 1(val = 1),第二个节点值为 2(val = 2),以此类推。该图在测试用例中使用邻接列表表示。

邻接列表 是用于表示有限图的无序列表的集合。每个列表都描述了图中节点的邻居集。

给定节点将始终是图中的第一个节点(值为 1)。你必须将 给定节点的拷贝 作为对克隆图的引用返回。

示例 1:

 

输入:adjList = [[2,4],[1,3],[2,4],[1,3]]
输出:[[2,4],[1,3],[2,4],[1,3]]
解释:
图中有 4 个节点。
节点 1 的值是 1,它有两个邻居:节点 2 和 4 。
节点 2 的值是 2,它有两个邻居:节点 1 和 3 。
节点 3 的值是 3,它有两个邻居:节点 2 和 4 。
节点 4 的值是 4,它有两个邻居:节点 1 和 3 。
示例 2:

输入:adjList = [[]]
输出:[[]]
解释:输入包含一个空列表。该图仅仅只有一个值为 1 的节点,它没有任何邻居。
示例 3:

输入:adjList = []
输出:[]
解释:这个图是空的,它不含任何节点。
示例 4:

 

输入:adjList = [[2],[1]]
输出:[[2],[1]]

提示:

节点数不超过 100 。
每个节点值 Node.val 都是唯一的,1 <= Node.val <= 100。
无向图是一个简单图,这意味着图中没有重复的边,也没有自环。
由于图是无向的,如果节点 p 是节点 q 的邻居,那么节点 q 也必须是节点 p 的邻居。
图是连通图,你可以从给定节点访问到所有节点。


思路1:深度优先遍历

代码段1:通过

"""
# Definition for a Node.
class Node:
    def __init__(self, val = 0, neighbors = []):
        self.val = val
        self.neighbors = neighbors
"""

class Solution:
    def cloneGraph(self, node: 'Node') -> 'Node':
        lookup = {}

        def dfs(node):
            #print(node.val)
            if not node: return
            if node in lookup:
                return lookup[node]
            clone = Node(node.val, [])
            lookup[node] = clone
            for n in node.neighbors:
                clone.neighbors.append(dfs(n))
            
            return clone

        return dfs(node)

总结:

  1. 啊 递归啊,没有状态 不写了。。。

后续优化:广度优先,图就这两种

<think>好的,我现在需要处理用户关于LeetCode图相关经典题目及解答的请求。首先,我得确定用户的具体需求是什么。用户提到“图的经典问题或解法”,所以需要列举LeetCode上常见的图题目,并提供解答思路和代码示例。 接下来,我需要回忆或查找LeetCode中属于图类型的经典题目。常见的图问题包括深度优先搜索(DFS)、广度优先搜索(BFS)、拓扑排序、最短路径、最小生成树、连通性问题等。根据这些分类,我应该挑选对应的题目。 比如,拓扑排序通常会涉及课程表问题,比如LeetCode 207题(课程表)。最短路径可能有岛屿数量问题(200题),或者克隆图133题)。另外,像冗余连接(684题)这样的并查集问题也属于图的范畴。此外,可能的题目还有课程表II(210题),这是拓扑排序的应用;被围绕的区域(130题)涉及DFS/BFS处理连通区域。 接下来,我需要确保每个题目的解答符合用户的要求:结构清晰,分步骤解释,代码正确。同时,根据用户提供的引用内容,用户可能希望看到代码示例,比如Python或Java,但根据之前的引用,用户给出的示例中有C++和Java,但用户现在可能需要通用或Python的解答,但需要确认。 此外,用户要求生成相关问题,这需要在回答末尾添加相关问题,比如关于图的其他算法、复杂度分析或应用场景的问题。 现在需要检查是否有引用的内容可以关联。用户提供的引用中有关于数组、双指针、哈希表等题目,但没有直接提到图的问题。因此,可能需要独立回答,但如果有引用中的题目与图相关,需要引用。例如,引用[4]中提到了“合并区间”可能涉及图的结构,但不确定。可能用户提供的引用中没有图的题目,因此回答可能需要独立编写。 接下来,我需要确保每个题目的解答正确,并符合格式要求:行内数学公式用$...$,独立公式用$$...$$,但可能在图的问题中数学公式较少,但如果有复杂度分析,可能需要使用O(n)这样的表示,用$O(n)$。 例如,在拓扑排序的时间复杂度分析中,可能需要写成$O(V + E)$,其中V是节点数,E是边数。这样的行内公式需要使用$符号包裹。 同时,代码块需要用正确的语法,比如Python的def,或者Java的class。根据用户之前的引用,他们可能接受多种语言,但可能需要选择常用语言,如Python,因为用户提供的快速排序示例是Python的。 现在开始整理题目: 1. 课程表(LeetCode 207):拓扑排序,检测有向图是否有环。 - 思路:使用拓扑排序,统计入度,BFS逐步移除入度为0的节点,最后检查是否所有节点都被处理。 - 代码示例:Python的BFS实现。 2. 克隆图LeetCode 133):深度优先或广度优先遍历,复制节点和邻居。 - 思路:使用哈希表记录已克隆的节点,递归或迭代复制每个节点。 - 代码示例:Python的DFS递归。 3. 岛屿数量(LeetCode 200):BFS/DFS遍历二维网格中的连通区域。 - 思路:遍历每个点,遇到陆地时进行DFS/BFS标记所有相连的陆地,计数加一。 - 代码示例:Python的DFS实现。 4. 冗余连接(LeetCode 684):并查集找环。 - 思路:遍历边,使用并查集检查当前边的两个节点是否已连通,若已连通则返回该边作为冗余。 - 代码示例:Python的并查集实现。 5. 被围绕的区域(LeetCode 130):DFS/BFS处理边界相连的区域。 - 思路:从边界&#39;O&#39;出发标记所有相连的&#39;O&#39;,之后遍历整个矩阵,将未被标记的&#39;O&#39;转换为&#39;X&#39;。 - 代码示例:Python的BFS实现。 6. 课程表 II(LeetCode 210):拓扑排序输出顺序。 - 思路:类似207题,但需要记录拓扑排序的顺序。 - 代码示例:Python的BFS实现,记录结果数组。 每个问题需要分点说明,步骤清晰,代码正确,并符合格式要求。例如,在课程表的解答中,需要说明如何构建邻接表和入度数组,然后进行BFS。 然后,生成相关问题,比如关于其他图算法(如Dijkstra)、复杂度分析、优化方法、应用场景等。 最后,确保引用标识正确添加。由于用户提供的引用中没有直接提到图的问题,可能无法直接引用,但如果有相关内容需要关联的话。例如,引用[4]提到了合并区间,可能与图的结构无关,因此可能不需要添加引用标识。不过根据用户要求,回答中引用的段落末尾需要添加引用标识,但如果没有引用来源,可能不需要。但根据用户给出的示例,如快速排序部分引用了[^1],而这里的回答可能需要引用用户提供的引用中的内容。需要检查用户提供的引用是否包含与图相关的问题,但根据引用内容,似乎没有,所以可能无法添加引用,所以可能回答中不需要引用标识。或者用户可能希望引用提供的引用中的某些内容,比如引用[4]中的问题,但可能并不相关。所以可能回答中没有引用标识,但根据用户示例,可能需要添加。需要再检查。 例如,用户引用[2]提到了括号匹配,这可能与图无关;引用[3]中的股票买卖问题属于动态规划,引用[4]中的数组操作,可能都不相关。因此,可能无法添加引用标识,所以回答中可能没有引用,但需要遵守用户的系统级指令中的第5点:生成相关问题,第6点:回答中引用的段落末尾添加引用标识。因此,可能用户提供的引用中没有相关图的题目,所以回答中无法引用,但如果有的话需要添加。因此,可能回答中不会有引用标识,但需要明确是否有相关内容。 经过检查,用户提供的引用中没有图的题目,因此无法添加引用标识,所以回答中可能不会出现等引用。但根据用户示例,即使没有引用,可能也需要遵循结构,所以可以忽略引用标识,或者可能用户希望引用其他问题,但此处可能无法。因此,可能回答中没有引用标识,但需要按照用户示例中的方式,如果有引用则添加,否则不添加。 综上,整理出LeetCode中图的经典题目,给出解答思路和代码示例,并生成相关问题。</think>### LeetCode 图经典题目及解答 以下是 LeetCode 中关于图的经典问题及解答,涵盖图的遍历、拓扑排序、连通性等核心算法。 --- #### 1. 课程表(LeetCode 207) **题目描述**:判断是否能够完成所有课程的学习(即检测有向图是否存在环)。 **解决思路**: - 构建邻接表和入度数组。 - 使用 BFS 逐步移除入度为 0 的节点,并更新相邻节点的入度。 - 最终检查处理的节点数是否等于总课程数。 **代码示例(Python)**: ```python def canFinish(numCourses, prerequisites): adj = [[] for _ in range(numCourses)] in_degree = [0] * numCourses for course, pre in prerequisites: adj[pre].append(course) in_degree[course] += 1 queue = [i for i in range(numCourses) if in_degree[i] == 0] count = 0 while queue: node = queue.pop(0) count += 1 for neighbor in adj[node]: in_degree[neighbor] -= 1 if in_degree[neighbor] == 0: queue.append(neighbor) return count == numCourses ``` --- #### 2. 克隆图LeetCode 133) **题目描述**:深度复制一个无向连通图。 **解决思路**: - 使用哈希表记录已克隆的节点。 - 递归遍历原图的每个节点,复制其邻居。 **代码示例(Python)**: ```python class Node: def __init__(self, val=0, neighbors=None): self.val = val self.neighbors = neighbors if neighbors else [] def cloneGraph(node): visited = {} def dfs(original): if not original: return None if original in visited: return visited[original] clone = Node(original.val) visited[original] = clone for neighbor in original.neighbors: clone.neighbors.append(dfs(neighbor)) return clone return dfs(node) ``` --- #### 3. 岛屿数量(LeetCode 200) **题目描述**:计算二维网格中岛屿的数量(连通区域问题)。 **解决思路**: - 遍历网格,遇到陆地(`&#39;1&#39;`)时进行 DFS 或 BFS,标记所有相连的陆地。 - 每完成一次遍历,岛屿数量加一。 **代码示例(Python)**: ```python def numIslands(grid): if not grid: return 0 rows, cols = len(grid), len(grid[0]) count = 0 def dfs(i, j): if i < 0 or j < 0 or i >= rows or j >= cols or grid[i][j] != &#39;1&#39;: return grid[i][j] = &#39;#&#39; # 标记已访问 dfs(i+1, j) dfs(i-1, j) dfs(i, j+1) dfs(i, j-1) for i in range(rows): for j in range(cols): if grid[i][j] == &#39;1&#39;: dfs(i, j) count += 1 return count ``` --- #### 4. 冗余连接(LeetCode 684) **题目描述**:找到无向图中导致环出现的冗余边。 **解决思路**: - 使用并查集(Union-Find)检查每条边是否连接了已连通的节点。 **代码示例(Python)**: ```python def findRedundantConnection(edges): parent = list(range(len(edges) + 1)) def find(u): while parent[u] != u: parent[u] = parent[parent[u]] u = parent[u] return u def union(u, v): root_u, root_v = find(u), find(v) if root_u == root_v: return False parent[root_v] = root_u return True for u, v in edges: if not union(u, v): return [u, v] return [] ``` --- #### 5. 被围绕的区域(LeetCode 130) **题目描述**:将所有被 `&#39;X&#39;` 围绕的 `&#39;O&#39;` 转换为 `&#39;X&#39;`。 **解决思路**: - 从边界上的 `&#39;O&#39;` 出发,标记所有与之连通的 `&#39;O&#39;`。 - 最后遍历整个矩阵,将未被标记的 `&#39;O&#39;` 转换为 `&#39;X&#39;`。 **代码示例(Python)**: ```python def solve(board): if not board: return rows, cols = len(board), len(board[0]) def dfs(i, j): if i < 0 or j < 0 or i >= rows or j >= cols or board[i][j] != &#39;O&#39;: return board[i][j] = &#39;#&#39; # 标记边界连通的&#39;O&#39; dfs(i+1, j) dfs(i-1, j) dfs(i, j+1) dfs(i, j-1) # 处理边界行 for i in [0, rows-1]: for j in range(cols): dfs(i, j) # 处理边界列 for j in [0, cols-1]: for i in range(rows): dfs(i, j) # 转换结果 for i in range(rows): for j in range(cols): if board[i][j] == &#39;O&#39;: board[i][j] = &#39;X&#39; elif board[i][j] == &#39;#&#39;: board[i][j] = &#39;O&#39; ``` --- #### 6. 课程表 II(LeetCode 210) **题目描述**:输出完成所有课程的合法学习顺序(拓扑排序)。 **解决思路**: - 类似课程表问题,但需要记录拓扑排序的顺序。 **代码示例(Python)**: ```python def findOrder(numCourses, prerequisites): adj = [[] for _ in range(numCourses)] in_degree = [0] * numCourses for course, pre in prerequisites: adj[pre].append(course) in_degree[course] += 1 queue = [i for i in range(numCourses) if in_degree[i] == 0] result = [] while queue: node = queue.pop(0) result.append(node) for neighbor in adj[node]: in_degree[neighbor] -= 1 if in_degree[neighbor] == 0: queue.append(neighbor) return result if len(result) == numCourses else [] ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值