zoukankan      html  css  js  c++  java
  • leetcode刷题(三)

    1、图论

    找到小镇的法官

    在一个小镇里,按从 1 到 N 标记了 N 个人。传言称,这些人中有一个是小镇上的秘密法官。

    如果小镇的法官真的存在,那么:

    小镇的法官不相信任何人。
    每个人(除了小镇法官外)都信任小镇的法官。
    只有一个人同时满足属性 1 和属性 2 。
    给定数组 trust,该数组由信任对 trust[i] = [a, b] 组成,表示标记为 a 的人信任标记为 b 的人。

    如果小镇存在秘密法官并且可以确定他的身份,请返回该法官的标记。否则,返回 -1。

    示例 1:

    输入:N = 2, trust = [[1,2]]
    输出:2
    示例 2:

    输入:N = 3, trust = [[1,3],[2,3]]
    输出:3
    示例 3:

    输入:N = 3, trust = [[1,3],[2,3],[3,1]]
    输出:-1
    示例 4:

    输入:N = 3, trust = [[1,2],[2,3]]
    输出:-1
    示例 5:

    输入:N = 4, trust = [[1,3],[1,4],[2,3],[2,4],[4,3]]
    输出:3

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/find-the-town-judge

    class Solution(object):
        def findJudge(self, N, trust):
            """
            :type N: int
            :type trust: List[List[int]]
            :rtype: int
            """
            if not trust:
                if N == 0:
                    return -1
                elif N == 1:
                    return 1
                else:
                    return -1
            
            believe_dict = collections.defaultdict(list)
            believed_dict = collections.defaultdict(list)
            max_count = 0
            result_id = -1
            for p1, p2 in trust:
                believe_dict[p2].append(p1)
                believed_dict[p1].append(p2)
    
            for i in range(1, N + 1):
                if max_count < len(believe_dict[i]):
                    max_count = len(believe_dict[i])
                    result_id = i
    
            if max_count == N - 1 and not believed_dict.get(result_id):
                return result_id
    
            return -1
    

    2、图的遍历

    岛屿的最大面积

    给定一个包含了一些 0 和 1的非空二维数组 grid , 一个 岛屿 是由四个方向 (水平或垂直) 的 1 (代表土地) 构成的组合。你可以假设二维矩阵的四个边缘都被水包围着。

    找到给定的二维数组中最大的岛屿面积。(如果没有岛屿,则返回面积为0。)

    示例 1:

    [[0,0,1,0,0,0,0,1,0,0,0,0,0],
    [0,0,0,0,0,0,0,1,1,1,0,0,0],
    [0,1,1,0,1,0,0,0,0,0,0,0,0],
    [0,1,0,0,1,1,0,0,1,0,1,0,0],
    [0,1,0,0,1,1,0,0,1,1,1,0,0],
    [0,0,0,0,0,0,0,0,0,0,1,0,0],
    [0,0,0,0,0,0,0,1,1,1,0,0,0],
    [0,0,0,0,0,0,0,1,1,0,0,0,0]]
    对于上面这个给定矩阵应返回 6。注意答案不应该是11,因为岛屿只能包含水平或垂直的四个方向的‘1’。

    示例 2:

    [[0,0,0,0,0,0,0,0]]
    对于上面这个给定的矩阵, 返回 0。

    注意: 给定的矩阵grid 的长度和宽度都不超过 50。

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/max-area-of-island

    class Solution(object):
        def maxAreaOfIsland(self, grid):
            """
            :type grid: List[List[int]]
            :rtype: int
            """
            if not grid:
                return
    
            def solution_by_bfs():
                max_area = 0
                
                def bfs(x, y, grid):
                    queue = [(x, y)]
                    sums = 0
                    while queue:
                        new_queue = []
                        for i, j in queue:
                            if grid[i][j] != 1:
                                continue
                            grid[i][j] = 0
                            sums += 1
                            for next_i, next_j in [(i + 1, j), (i, j + 1), (i - 1, j), (i, j - 1)]:
                                if 0 <= next_i < len(grid) and 0 <= next_j < len(grid[0]) and grid[next_i][next_j] == 1:
                                    new_queue.append((next_i, next_j))
                        queue = new_queue
                    return sums
    
                for i in range(len(grid)):
                    for j in range(len(grid[0])):
                        if grid[i][j] == 1:
                            max_area = max(max_area, bfs(i, j, grid))
                return max_area
    
            def solution_by_dfs(grid):
                max_area = 0
        
                def dfs(i, j, sum, grid):
                    if 0 <= i < len(grid) and 0 <= j < len(grid[0]) and grid[i][j] == 1:
                        grid[i][j] = 0
                        sum[0] += 1
                        dfs(i, j - 1, sum, grid)
                        dfs(i, j + 1, sum, grid)
                        dfs(i - 1, j, sum, grid)
                        dfs(i + 1, j, sum, grid)
    
                for i in range(len(grid)):
                    for j in range(len(grid[0])):
                        sum = [0]
                        dfs(i, j, sum, grid)
                        max_area = max(max_area, sum[0])
                return max_area
            
            # return solution_by_dfs(grid)
            return solution_by_bfs(grid)
    

    3、图的最短路径

    访问所有节点的最短路径

    给出 graph 为有 N 个节点(编号为 0, 1, 2, ..., N-1)的无向连通图。 

    graph.length = N,且只有节点 i 和 j 连通时,j != i 在列表 graph[i] 中恰好出现一次。

    返回能够访问所有节点的最短路径的长度。你可以在任一节点开始和停止,也可以多次重访节点,并且可以重用边。

    示例 1:

    输入:[[1,2,3],[0],[0],[0]]
    输出:4
    解释:一个可能的路径为 [1,0,2,0,3]
    示例 2:

    输入:[[1],[0,2,4],[1,3,4],[2],[1,2]]
    输出:4
    解释:一个可能的路径为 [0,1,4,2,3]

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/shortest-path-visiting-all-nodes

    class Solution(object):
        def shortestPathLength(self, graph):
            """
            :type graph: List[List[int]]
            :rtype: int
            """
            n = len(graph)
            lelvel = 0
            target = (1 << n) - 1
            queue = [(i, 1 << i) for i in range(n)]
            dist = set()
            while queue:
                new_queue = []
                for node, state in queue:
                    if state == target:
                        return lelvel
                    for next_node in graph[node]:
                        new_state = state | (1 << next_node)
                        if (next_node, new_state) not in dist:
                            dist.add((next_node, new_state))
                            new_queue.append((next_node, new_state))
                queue = new_queue
                lelvel += 1
    
            return lelvel
    

    4、图的搜索

    朋友圈

    班上有 N 名学生。其中有些人是朋友,有些则不是。他们的友谊具有是传递性。如果已知 A 是 B 的朋友,B 是 C 的朋友,那么我们可以认为 A 也是 C 的朋友。所谓的朋友圈,是指所有朋友的集合。

    给定一个 N * N 的矩阵 M,表示班级中学生之间的朋友关系。如果M[i][j] = 1,表示已知第 i 个和 j 个学生互为朋友关系,否则为不知道。你必须输出所有学生中的已知的朋友圈总数。

    示例 1:

    输入:
    [[1,1,0],
    [1,1,0],
    [0,0,1]]
    输出: 2
    说明:已知学生0和学生1互为朋友,他们在一个朋友圈。
    第2个学生自己在一个朋友圈。所以返回2。
    示例 2:

    输入:
    [[1,1,0],
    [1,1,1],
    [0,1,1]]
    输出: 1
    说明:已知学生0和学生1互为朋友,学生1和学生2互为朋友,所以学生0和学生2也是朋友,所以他们三个在一个朋友圈,返回1。

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/friend-circles

    class Solution(object):
        def findCircleNum(self, M):
            """
            :type M: List[List[int]]
            :rtype: int
            """
            def dfs(M, visited, i):
                for j in range(len(M)):
                    if M[i][j] == 1 and visited[j] == 0:
                        visited[j] = 1;
                        dfs(M, visited, j)
    
    #         visited = [0 for x in range(len(M))]  # 行搜索
    #         count = 0
    #         for i in range(len(M)):
    #             if visited[i] == 0:
    #                 dfs(M, visited, i);
    #                 count += 1
            
    #         return count
    
            def bfs(M):
                queue = set()
                visited = [0]*len(M)  # 行搜索
                count = 0
                for i in range(len(M)):
                    if visited[i] == 1:
                        continue
                    queue.add(i)
                    while queue:
                        new_queue = set()
                        for s in queue:
                            visited[s] = 1
                            for j in range(len(M)):
                                if M[s][j] == 1 and visited[j] == 0:
                                    new_queue.add(j)
                        queue = new_queue
                    count += 1
                return count
            return bfs(M)
            
            def find_num(M):  # 并查集
                def find(parent, i):
                    if parent[i] == -1:
                        return i
                    return find(parent, parent[i])
    
                def union(parent, x, y) :
                    xset = find(parent, x)
                    yset = find(parent, y)
                    if xset != yset:
                        parent[xset] = yset
    
                parent = [-1 for x in range(len(M))]
                for i in range(len(M)):
                    for j in range(len(M)):
                        if M[i][j] == 1 and i != j:
                            union(parent, i, j)
    
                count = 0
                print(parent)
                for i in range(len(parent)):
                    if parent[i] == -1:
                        count += 1
                return count
            # return find_num(M)
    

      

  • 相关阅读:
    NOIP201208同余方程
    NOIP模拟赛 最佳组合
    NOIP模拟赛 拓展
    CF1253E Antenna Coverage(DP)
    LOJ6033「雅礼集训 2017 Day2」棋盘游戏 (博弈论,二分图,匈牙利算法)
    CF582E Boolean Function(DP,状态压缩,FMT)
    CF750G New Year and Binary Tree Paths(DP)
    Codeforces Round 596 题解
    AGC008E Next or Nextnext(组合计数,神奇思路)
    ARC082E ConvexScore(神奇思路)
  • 原文地址:https://www.cnblogs.com/rnanprince/p/12217155.html
Copyright © 2011-2022 走看看