9.2.2 图的遍历LeetCode题目 —— Find the Town Judge & Clone Graph & Keys and Rooms

在LeetCode的题目中,图有多种表示方法。

1. 题目133一类,用一个顶点表示整张图,比较少见,和二叉树的情形类似,因此需要整张图顶点是连通的;

2. 题目997一类,还有后面207,210,310等题目用边来表示图,不用邻接表是因为邻接表会一下暴露答案吧,或者基于一定的实际含义;

2. 题目841一类,典型的邻接表的表示方法,也很常见。

 

133. Clone Graph

Given a reference of a node in a connected undirected graph.

Return a deep copy (clone) of the graph.

Each node in the graph contains a val (int) and a list (List[Node]) of its neighbors.

 

题解

1. 注意题目的入参和出参,都是Node结构,而题目说明及例子解释绕了个弯。2. 题目的解法就是遍历的过程中,进行深拷贝,和二叉树相关内容类似,要重新新建图的顶点并按原来连接。

看方法一,通过队列进行广度优先的搜索,按遍历顺序复制顶点即邻居;visit存放已经完成复制的点,dic存放顶点值和复制后的顶点的映射;在遍历的过程中,要把cur当前顶点的所有邻居添加到self.neighbors , 邻居如果已经新建则直接引用,未新建则新建一个,注意新建点的时候,他的self.neighbors是空的,并没有完成该点的复制,只有在while 循环完成cur点才是复制完的。

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

class Solution:
    def cloneGraph(self, node: 'Node') -> 'Node':
        dic = dict()
        visit = set()
        dq = []
        
        if not node:
            return None
        dq.append(node)
        head = Node(node.val)
        dic[node.val] = head
        while len(dq) > 0:
            cur = dq.pop()
            if cur.val in visit:
                continue
            tmp = dic[cur.val]
            for node_ in cur.neighbors:
                if node_.val in dic.keys():
                    chi = dic[node_.val]
                else:
                    chi = Node(node_.val)
                    dic[node_.val] = chi
                tmp.neighbors.append(chi)
                dq.append(node_)
            visit.add(cur.val)
            
        return head

方法二,递归实现的深度优先遍历,代码量较少,dic既用于查找也起到了visit访问查找的作用,dfs两个参数,新旧两张图的相同顶点,主要就是把所有邻居的复制品的引用加入到该顶点的邻居表。

class Solution:
    def cloneGraph(self, node: 'Node') -> 'Node':
        if not node:
            return None
        dic = {}
        head = Node(node.val)
        dic[node.val] = head
        def dfs(x, copy):
            for chl in x.neighbors:
                if chl.val in dic.keys():
                    cur = dic[chl.val]
                    copy.neighbors.append(cur)
                else:
                    cp = Node(chl.val)
                    copy.neighbors.append(cp)
                    dic[chl.val] = cp
                    dfs(chl, cp)
        tmp = head
        dfs(node, tmp)
        return head

997 Find the Town Judge

In a town, there are N people labelled from 1 to N.  There is a rumor that one of these people is secretly the town judge.

If the town judge exists, then:

  1. The town judge trusts nobody.
  2. Everybody (except for the town judge) trusts the town judge.
  3. There is exactly one person that satisfies properties 1 and 2.

You are given trust, an array of pairs trust[i] = [a, b] representing that the person labelled a trusts the person labelled b.

If the town judge exists and can be identified, return the label of the town judge.  Otherwise, return -1.

题解:

该题用边表示图,读题意其实是让我们找到一个点,该点的出度(信任别人)为0,入度(被人信任)为n-1,因此鄙人的解法就是直接统计每个点的入度和出度,存储在列表里,下标对应1-N每个人,最后线性过一遍即可。解法的时空效率都很不错。

class Solution:
    def findJudge(self, N: int, trust: List[List[int]]) -> int:
        if N == 1:
            return 1
        totrust = [0] * N
        betrust = [0] * N
        for edge in trust:
            totrust[edge[0]-1] += 1
            betrust[edge[1]-1] += 1
        ret = []
        for i, n in enumerate(betrust):
            if n == N-1 and totrust[i] == 0:
                return i+1
        return -1

841. Keys and Rooms

There are N rooms and you start in room 0.  Each room has a distinct number in 0, 1, 2, ..., N-1, and each room may have some keys to access the next room. 

Formally, each room i has a list of keys rooms[i], and each key rooms[i][j] is an integer in [0, 1, ..., N-1] where N = rooms.length.  A key rooms[i][j] = v opens the room with number v.

Initially, all the rooms start locked (except for room 0). 

You can walk back and forth between rooms freely.

Return true if and only if you can enter every room.

题解:

我觉得这应该算简单级别题目,最直接的邻接表表示图,然后我们验证从顶点0开始图是连通的就行。用队列直接一个bfs看一下就行。

class Solution:
    def canVisitAllRooms(self, rooms: List[List[int]]) -> bool:
        visit = set()
        n = len(rooms)
        dq = [0]
        
        while len(visit) < n and len(dq) > 0:
            cur = dq.pop()
            if cur in visit:
                continue
            visit.add(cur)
            dq.extend(rooms[cur])
        
        return len(visit) == n

这一篇是图相关的最基本题目,只考察简单的遍历。下面一篇的题目会稍有难度

9.2.3 图的遍历及路径 —— Reconstruct Itinerary & All Paths From Source to Target

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值