📜  门| GATE-CS-2017(套装2)|第 64 题(1)

📅  最后修改于: 2023-12-03 15:42:19.195000             🧑  作者: Mango

门| GATE-CS-2017(套装2)|第 64 题

这是 GATE-CS-2017(套装2)中的一道题目,主要考察图的遍历和迭代算法。

题目描述

给定一张无向图 G(V,E),其中 V 表示节点集合,E 表示边集合。你需要实现一个函数 countLeafVertices(G),它能够返回图中的叶子节点(degree 为 1 的节点)的数量。

函数原型如下:

def countLeafVertices(G):
    # TODO: count leaf vertices in the graph
    pass

函数参数说明:

  • G: 无向图 G,用一个邻接表表示。邻接表是一个长度为 |V| 的列表,列表的第 i 项表示节点 i 的邻居。

函数返回值说明:

  • 返回一个整数值,表示图中的叶子节点数量。
解题思路

题目要求求解图中的叶子节点数量,我们可以通过遍历图的方式来求解。遍历的方式有很多种,这里提供两种常见的遍历方式:

DFS(深度优先搜索)

DFS(深度优先搜索)是常用的图遍历算法,它从图的某一个顶点出发开始遍历,直到所有的可达节点都被访问过为止,具体算法过程如下:

  1. 访问起点 v;
  2. 标记 v 为已访问;
  3. 对于 v 的所有邻居 w,如果 w 没有被标记为已访问过,则对 w 做递归调用。

下面是 Python 实现的 DFS 算法:

# 深度优先搜索
def dfs(v, visited, adj):
    visited[v] = True
    count = 1 # 默认情况下,v 是叶子节点
    
    # 遍历 v 的邻居节点
    for w in adj[v]:
        if not visited[w]:
            count += dfs(w, visited, adj)
    
    return count

dfs(v, visited, adj) 函数中,v 表示当前节点,visited 表示图中所有节点的访问情况(初始时都为 False),adj 是图的邻接矩阵。函数返回的是以 v 为根节点所构成的子树中叶子节点的数量。

调用 countLeafVertices(G) 函数的时候,我们可以随机挑选一个节点作为根节点开始遍历,最后把所有节点的结果累加起来。所以函数的实现可以写成这样:

def countLeafVertices(G):
    n = len(G)
    visited = [False] * n
    count = 0
    
    # 遍历图中的所有节点
    for v in range(n):
        if not visited[v]:
            degree = len(G[v]) # 当前节点的度数
            if degree == 1: # 当前节点是叶子节点
                count += 1
            else: # 当前节点不是叶子节点
                count += dfs(v, visited, G)
    
    return count
BFS(广度优先搜索)

BFS(广度优先搜索)是另一种常见的图遍历算法,它从图的某一个顶点出发开始遍历,按照距离从近到远的顺序进行遍历,直到所有的可达节点都被访问过为止,具体算法过程如下:

  1. 创建一个队列,起始节点 v 入队;
  2. 标记 v 为已访问;
  3. 取出队列头部的节点 w,遍历 w 的所有邻居节点 x,并且对于 x 没有被标记为已访问过的,将 x 入队,并标记为已访问;
  4. 重复步骤 3,直到队列为空。

下面是 Python 实现的 BFS 算法:

# 宽度优先搜索
def bfs(v, visited, adj):
    queue = [v] # 起始节点入队
    visited[v] = True
    count = 1 # 默认情况下,v 是叶子节点
    
    # 遍历队列中的所有节点
    while queue:
        w = queue.pop(0) # 取出队列头部的节点
        for x in adj[w]: # 遍历 w 的所有邻居节点 x
            if not visited[x]:
                visited[x] = True
                count += 1 # x 是w的叶子节点
                queue.append(x) # 将 x 入队
    
    return count

与 DFS 类似,BFS 遍历也要遍历图中的所有节点,然后每个节点作为根节点分别计算以它为根节点的子树中叶子节点的数量。最后把所有节点的结果累加起来。函数的实现可以写成这样:

def countLeafVertices(G):
    n = len(G)
    visited = [False] * n
    count = 0
    
    # 遍历图中的所有节点
    for v in range(n):
        if not visited[v]:
            degree = len(G[v]) # 当前节点的度数
            if degree == 1: # 当前节点是叶子节点
                count += 1
            else: # 当前节点不是叶子节点
                count += bfs(v, visited, G)
    
    return count
代码实现

最终实现的代码如下:

# 深度优先搜索
def dfs(v, visited, adj):
    visited[v] = True
    count = 1 # 默认情况下,v 是叶子节点
    
    # 遍历 v 的邻居节点
    for w in adj[v]:
        if not visited[w]:
            count += dfs(w, visited, adj)
    
    return count

# 宽度优先搜索
def bfs(v, visited, adj):
    queue = [v] # 起始节点入队
    visited[v] = True
    count = 1 # 默认情况下,v 是叶子节点
    
    # 遍历队列中的所有节点
    while queue:
        w = queue.pop(0) # 取出队列头部的节点
        for x in adj[w]: # 遍历 w 的所有邻居节点 x
            if not visited[x]:
                visited[x] = True
                count += 1 # x 是w的叶子节点
                queue.append(x) # 将 x 入队
    
    return count

def countLeafVertices(G):
    n = len(G)
    visited = [False] * n
    count = 0
    
    # 遍历图中的所有节点
    for v in range(n):
        if not visited[v]:
            degree = len(G[v]) # 当前节点的度数
            if degree == 1: # 当前节点是叶子节点
                count += 1
            else: # 当前节点不是叶子节点
                count += dfs(v, visited, G)
    
    return count
Markdown 代码片段
# 门| GATE-CS-2017(套装2)|第 64 题

这是 GATE-CS-2017(套装2)中的一道题目,主要考察图的遍历和迭代算法。

## 题目描述

给定一张无向图 G(V,E),其中 V 表示节点集合,E 表示边集合。你需要实现一个函数 `countLeafVertices(G)`,它能够返回图中的叶子节点(degree 为 1 的节点)的数量。

函数原型如下:

```python
def countLeafVertices(G):
    # TODO: count leaf vertices in the graph
    pass

函数参数说明:

  • G: 无向图 G,用一个邻接表表示。邻接表是一个长度为 |V| 的列表,列表的第 i 项表示节点 i 的邻居。

函数返回值说明:

  • 返回一个整数值,表示图中的叶子节点数量。
解题思路

题目要求求解图中的叶子节点数量,我们可以通过遍历图的方式来求解。遍历的方式有很多种,这里提供两种常见的遍历方式:

DFS(深度优先搜索)

DFS(深度优先搜索)是常用的图遍历算法,它从图的某一个顶点出发开始遍历,直到所有的可达节点都被访问过为止。

BFS(广度优先搜索)

BFS(广度优先搜索)是另一种常见的图遍历算法,它从图的某一个顶点出发开始遍历,按照距离从近到远的顺序进行遍历,直到所有的可达节点都被访问过为止。

Python 代码实现
# 深度优先搜索
def dfs(v, visited, adj):
    visited[v] = True
    count = 1 # 默认情况下,v 是叶子节点
    
    # 遍历 v 的邻居节点
    for w in adj[v]:
        if not visited[w]:
            count += dfs(w, visited, adj)
    
    return count

# 宽度优先搜索
def bfs(v, visited, adj):
    queue = [v] # 起始节点入队
    visited[v] = True
    count = 1 # 默认情况下,v 是叶子节点
    
    # 遍历队列中的所有节点
    while queue:
        w = queue.pop(0) # 取出队列头部的节点
        for x in adj[w]: # 遍历 w 的所有邻居节点 x
            if not visited[x]:
                visited[x] = True
                count += 1 # x 是w的叶子节点
                queue.append(x) # 将 x 入队
    
    return count

def countLeafVertices(G):
    n = len(G)
    visited = [False] * n
    count = 0
    
    # 遍历图中的所有节点
    for v in range(n):
        if not visited[v]:
            degree = len(G[v]) # 当前节点的度数
            if degree == 1: # 当前节点是叶子节点
                count += 1
            else: # 当前节点不是叶子节点
                count += dfs(v, visited, G)
    
    return count
Markdown 代码片段
# 门| GATE-CS-2017(套装2)|第 64 题

这是 GATE-CS-2017(套装2)中的一道题目,主要考察图的遍历和迭代算法。

## 题目描述

给定一张无向图 G(V,E),其中 V 表示节点集合,E 表示边集合。你需要实现一个函数 `countLeafVertices(G)`,它能够返回图中的叶子节点(degree 为 1 的节点)的数量。

函数原型如下:

```python
def countLeafVertices(G):
    # TODO: count leaf vertices in the graph
    pass

函数参数说明:

  • G: 无向图 G,用一个邻接表表示。邻接表是一个长度为 |V| 的列表,列表的第 i 项表示节点 i 的邻居。

函数返回值说明:

  • 返回一个整数值,表示图中的叶子节点数量。
解题思路

题目要求求解图中的叶子节点数量,我们可以通过遍历图的方式来求解。遍历的方式有很多种,这里提供两种常见的遍历方式:

DFS(深度优先搜索)

DFS(深度优先搜索)是常用的图遍历算法,它从图的某一个顶点出发开始遍历,直到所有的可达节点都被访问过为止,具体算法过程如下:

  1. 访问起点 v;
  2. 标记 v 为已访问;
  3. 对于 v 的所有邻居 w,如果 w 没有被标记为已访问过,则对 w 做递归调用。

在 DFS 算法中,我们需要每个节点作为根节点分别计算以它为根节点的子树中叶子节点的数量,最后把所有节点的结果累加起来。

BFS(广度优先搜索)

BFS(广度优先搜索)是另一种常见的图遍历算法,它从图的某一个顶点出发开始遍历,按照距离从近到远的顺序进行遍历,直到所有的可达节点都被访问过为止,具体算法过程如下:

  1. 创建一个队列,起始节点 v 入队;
  2. 标记 v 为已访问;
  3. 取出队列头部的节点 w,遍历 w 的所有邻居节点 x,并且对于 x 没有被标记为已访问过的,将 x 入队,并标记为已访问;
  4. 重复步骤 3,直到队列为空。

在 BFS 算法中,我们同样需要每个节点作为根节点分别计算以它为根节点的子树中叶子节点的数量,最后把所有节点的结果累加起来。

函数 countLeafVertices(G) 的具体实现中,我们可以先遍历图中的所有节点,判断当前节点的度数,如果是叶子节点则计数器加一,并跳过本轮遍历。如果不是叶子节点,则调用 DFS 或 BFS 算法计算以该节点为根节点的子树中叶子节点的数量,最后累加到计数器中,继续下一轮的遍历。

Python 代码实现

最终实现的代码如下:

# 深度优先搜索
def dfs(v, visited, adj):
    visited[v] = True
    count = 1 # 默认情况下,v 是叶子节点
    
    # 遍历 v 的邻居节点
    for w in adj[v]:
        if not visited[w]:
            count += dfs(w, visited, adj)
    
    return count

# 宽度优先搜索
def bfs(v, visited, adj):
    queue = [v] # 起始节点入队
    visited[v] = True
    count = 1 # 默认情况下,v 是叶子节点
    
    # 遍历队列中的所有节点
    while queue:
        w = queue.pop(0) # 取出队列头部的节点
        for x in adj[w]: # 遍历 w 的所有邻居节点 x
            if not visited[x]:
                visited[x] = True
                count += 1 # x 是w的叶子节点
                queue.append(x) # 将 x 入队
    
    return count

def countLeafVertices(G):
    n = len(G)
    visited = [False] * n
    count = 0
    
    # 遍历图中的所有节点
    for v in range(n):
        if not visited[v]:
            degree = len(G[v]) # 当前节点的度数
            if degree == 1: # 当前节点是叶子节点
                count += 1
            else: # 当前节点不是叶子节点
                count += dfs(v, visited, G) # 或者调用 bfs 函数
    
    return count

该函数的时间复杂度是 O(|V| + |E|),空间复杂度也是 O(|V| + |E|)。