leetcode
leetcode 1651 ~ 1700
最多邀请的个数

最多邀请的个数

难度:

标签:

题目描述

代码结果

运行时间: 96 ms, 内存: 18.5 MB


/*
 * Leetcode Problem 1820: Maximum Number of Invitations
 * 
 * Problem Description: Given an array of integers where each integer represents the index of another person that can be invited to a party, the task is to find the maximum number of people that can be invited such that no two people invite each other.
 * 
 * Approach using Java Streams:
 * 1. Convert the invitations array to a list of pairs representing the graph edges.
 * 2. Use Streams to process and find cycles and maximum path lengths.
 * 3. Combine the results to find the maximum number of invites.
 */

import java.util.*;
import java.util.stream.*;

public class MaxInvitationsStream {
    public int maximumInvitations(int[] favorite) {
        int n = favorite.length;
        List<Integer>[] graph = new ArrayList[n];
        for (int i = 0; i < n; i++) {
            graph[i] = new ArrayList<>();
        }
        for (int i = 0; i < n; i++) {
            graph[favorite[i]].add(i);
        }

        int[] dp = new int[n];
        boolean[] visited = new boolean[n];
        boolean[] inStack = new boolean[n];

        return IntStream.range(0, n).filter(i -> !visited[i]).map(i -> dfs(i, graph, dp, visited, inStack)).max().orElse(0);
    }

    private int dfs(int node, List<Integer>[] graph, int[] dp, boolean[] visited, boolean[] inStack) {
        if (visited[node]) {
            return dp[node];
        }
        visited[node] = true;
        inStack[node] = true;
        int maxLength = 1;

        for (int nextNode : graph[node]) {
            if (!visited[nextNode]) {
                maxLength = Math.max(maxLength, 1 + dfs(nextNode, graph, dp, visited, inStack));
            } else if (inStack[nextNode]) {
                maxLength = 0;  // Cycle detected
            }
        }

        dp[node] = maxLength;
        inStack[node] = false;
        return dp[node];
    }

    public static void main(String[] args) {
        MaxInvitationsStream mis = new MaxInvitationsStream();
        int[] favorite = {2, 2, 1, 2};
        System.out.println(mis.maximumInvitations(favorite));  // Output: 3
    }
}

解释

方法:

这道题可以使用匈牙利算法来求解二分图的最大匹配。首先,将给定的网格视为一个二分图,其中每个行和列分别代表二分图的两个部分。如果网格中的某个位置是1,那么就在对应的行和列之间添加一条边。接着,使用匈牙利算法来找出二分图的最大匹配。匈牙利算法的核心思想是通过增广路径来不断地增加匹配的数量。当找不到增广路径时,算法结束,此时的匹配数量就是二分图的最大匹配。

时间复杂度:

O((m+n) * E)

空间复杂度:

O(E + V)

代码细节讲解

🦆
为什么需要将网格问题转换成二分图来解决,这样的转换有什么好处?
将网格问题转换成二分图可以利用已有的图论算法来求解问题,这种转换能够明确地表达元素间的关系和约束条件。在二分图中,每个顶点只与对立集合中的顶点相连,不存在同集合内的顶点直接连接,这样的特性使得二分图的问题(如求最大匹配)有清晰的算法解决方案。对于网格问题,将行和列分别看作二分图的两部分,可以将网格中元素的相互作用转化为行与列之间的连接关系,从而使用图论中的匹配算法来优化和简化问题求解过程。
🦆
在匈牙利算法中,如何确定一个路径是增广路径,它的具体标准是什么?
在匈牙利算法中,增广路径是指从一个未匹配的左顶点开始,通过交错的匹配和非匹配边,最终到达一个未匹配的右顶点的路径。具体来说,增广路径的标准是:路径的起始点和终点顶点均未被匹配,且路径上的边交替出现在匹配边和非匹配边之间。找到这样的路径后,可以通过反转路径上匹配边和非匹配边的状态来增加匹配的总数,这是算法核心增加匹配数量的方法。
🦆
匈牙利算法中提到的‘增广路径’是在哪一步操作中被寻找的,能否详细解释其过程?
在匈牙利算法中,增广路径的寻找是在算法的主循环中进行的。具体过程如下: 1. 初始化所有左顶点为未匹配状态,遍历每个未匹配的左顶点作为起始点。 2. 使用广度优先搜索(BFS)或深度优先搜索(DFS)从当前未匹配的左顶点出发,探索所有可能的路径。 3. 对于当前顶点的每一个相邻顶点,检查是否未匹配或者是否可以通过递归地寻找该顶点的匹配点的增广路径来释放该顶点,使得当前顶点也变得可匹配。 4. 如果找到从当前左顶点出发的增广路径,则更新路径上的匹配关系,即交换匹配边和非匹配边的状态。 5. 重复此过程,直到无法找到新的增广路径为止。每次找到增广路径后,匹配的数量会增加一个单位,直至算法终止。

相关问题