Leetcode0547. Number of provinces (medium, DFS, BFS, and collection)

content

1. Topic description

2. Problem solving analysis

3. Code implementation


content

1. Topic description

2. Method 1: Graph Traversal

2.1 Ideas

2.2 Code Implementation

3. Method 2: Consolidate collections

3.1 Ideas

3.2 Code Implementation


1. Topic description

There is  n a city, some of which are connected to each other and others that are not. If  a the city is  b directly connected to the city  b and the city  c is directly connected to the city, then the city  is  indirectly connected to the a city  .c

A province  is a group of directly or indirectly connected cities, excluding other unconnected cities.

Give you a  n x n matrix  isConnected , which  isConnected[i][j] = 1 means that the  i th city and the  j th city are directly connected, and the  isConnected[i][j] = 0 two are not directly connected.

Returns the number of  provinces in the matrix  .

Example 1:

Input: isConnected = [[1,1,0],[1,1,0],[0,0,1]]
 Output: 2

Example 2:

Input: isConnected = [[1,0,0],[0,1,0],[0,0,1]]
 Output: 3

hint:

  • 1 <= n <= 200
  • n == isConnected.length
  • n == isConnected[i].length
  • isConnected[i][j] for  1 or 0
  • isConnected[i][i] == 1
  • isConnected[i][j] == isConnected[j][i]

Source: LeetCode
Link: https://leetcode-cn.com/problems/number-of-provinces The
copyright belongs to LeetCode.com. For commercial reprints, please contact the official authorization, and for non-commercial reprints, please indicate the source.

2. Method 1: Graph Traversal

2.1 Ideas

        The translation of provinces into "province" really has to be accepted. Fortunately, this is a symbol and does not affect the solution.

        In essence, it is to find the number of connected regions in a graph.

        This graph is represented by an adjacency matrix represented by isConnected.

        Since it is a full graph traversal, either breadth-first search or depth-first search can be dealt with. Several such topics have appeared earlier in this "Topics in Graph Theory Fundamentals" series. Refer to "Graph Theory Fundamentals" in Leetcode's daily problem-solving notes (dynamic update...) of Benniu Slow Farming .

        The representation of the adjacency matrix makes it very convenient to query adjacent nodes.

2.2 Code Implementation

from typing import List
from collections import deque

class Solution:
    def findCircleNum(self, isConnected: List[List[int]]) -> int:
        if len(isConnected)==0:
            return 0
        
        N         = len(isConnected)
        islandCnt = 0
        q         = deque()
        visited   = set()
        for node in range(N):
            # print(node, visited)
            # find the next unvisited node
            if node not in visited:
                # print("Start node of the next island: ", node)
                # Start from this node to search the connected sub-graph
                q.append(node)
                visited.add(node)
                while len(q) > 0:
                    tmp = q.pop()
                    for k in range(N):
                        if isConnected[tmp][k]==1 and k not in visited:
                            q.append(k)
                            visited.add(k)
                islandCnt += 1
                
        return islandCnt        
    
if __name__ == '__main__':
    
    sln = Solution()
    
    isConnected = [[1,1,0],[1,1,0],[0,0,1]]
    print(sln.findCircleNum(isConnected))
    
    isConnected = [[1,0,0],[0,1,0],[0,0,1]]
    print(sln.findCircleNum(isConnected))

        The above code uses "q.pop()", which is paired with q.append(), indicating that q is used as a stack, so it represents a depth-first search. And if it is changed to "q.popleft()", it means that q is used as a queue, so that the breadth-first search is programmed. 

        Execution time: 44 ms, beat 88.42% of users in all Python3 commits

        Memory consumption: 15.4 MB, beating 42.50% of users across all Python3 commits

3. Method 2: Consolidate collections

3.1 Ideas

        Another way to calculate the number of connected components is to use union-find. Initially, each province is initialized to belong to a different connected component. Traverse the matrix isConnected, if there is a connected relationship between two provinces, they belong to the same connected component, and merge them.

        After traversing all elements of the matrix isConnected, the total number of remaining connected components is the total number of provinces.

        In the following implementation, groupID is used to store the ID number of the group to which the corresponding node belongs. Each province is initialized to contain only its own group on initialization. groupID is the ID or index number of each province.

        Then traverse from small to large. For each province, query the node with the largest index number among its adjacent nodes, and merge itself into the group of the province with the largest index number. In the end, the number of provinces whose group number has not changed is the last remaining group number, which is the number of provinces required in this question.

3.2 Code Implementation

class Solution:
    def findCircleNum_union_find(self, isConnected: List[List[int]]) -> int:
        def find(index: int) -> int:
            # Find the group to which the index belongs
            if groupID[index] != index:
                groupID[index] = find(groupID[index])
            return groupID[index]
        
        def union(index1: int, index2: int):
            # Join index1 into the group which index2 belongs to
            groupID[find(index1)] = find(index2)
        
        # Initialization.
        # Start from the state in which each province belongs to the own-group
        # Each group has one province with the same index as its initial root.
        groupID      = list(range(len(isConnected)))
        
        # For each group, find the (directly or indirectly) connected province and
        # join itself into the later group
        for i in range(len(isConnected)):
            for j in range(i + 1, len(isConnected)):
                if isConnected[i][j] == 1:
                    union(i, j)
        
        numGroup = sum(groupID[i] == i for i in range(len(isConnected)))
        return numGroup

        Execution time: 56 ms, beating 44.57% of users across all Python3 commits

        Memory consumption: 15.3 MB, beating 54.80% of users across all Python3 commits

        Back to the main directory: Leetcode daily problem-solving notes (dynamic update...)

Guess you like

Origin blog.csdn.net/chenxy_bwave/article/details/124190467
Recommended