leetcode
leetcode 2151 ~ 2200
添加边使所有节点度数都为偶数

添加边使所有节点度数都为偶数

难度:

标签:

题目描述

There is an undirected graph consisting of n nodes numbered from 1 to n. You are given the integer n and a 2D array edges where edges[i] = [ai, bi] indicates that there is an edge between nodes ai and bi. The graph can be disconnected.

You can add at most two additional edges (possibly none) to this graph so that there are no repeated edges and no self-loops.

Return true if it is possible to make the degree of each node in the graph even, otherwise return false.

The degree of a node is the number of edges connected to it.

 

Example 1:

Input: n = 5, edges = [[1,2],[2,3],[3,4],[4,2],[1,4],[2,5]]
Output: true
Explanation: The above diagram shows a valid way of adding an edge.
Every node in the resulting graph is connected to an even number of edges.

Example 2:

Input: n = 4, edges = [[1,2],[3,4]]
Output: true
Explanation: The above diagram shows a valid way of adding two edges.

Example 3:

Input: n = 4, edges = [[1,2],[1,3],[1,4]]
Output: false
Explanation: It is not possible to obtain a valid graph with adding at most 2 edges.

 

Constraints:

  • 3 <= n <= 105
  • 2 <= edges.length <= 105
  • edges[i].length == 2
  • 1 <= ai, bi <= n
  • ai != bi
  • There are no repeated edges.

代码结果

运行时间: 180 ms, 内存: 48.0 MB


/*
 * 题目思路:
 * 1. 计算每个节点的度数。
 * 2. 找出度数为奇数的节点。
 * 3. 如果奇数节点数为0,则所有节点度数已经是偶数,返回true。
 * 4. 如果奇数节点数为2,可以通过添加一条边来使得所有节点度数为偶数,返回true。
 * 5. 如果奇数节点数为4,可以通过添加两条边来使得所有节点度数为偶数,返回true。
 * 6. 其他情况无法通过添加至多两条边来实现所有节点度数为偶数,返回false。
 */

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

public class SolutionStream {
    public boolean isPossible(int n, int[][] edges) {
        int[] degree = new int[n + 1];
        Map<Integer, Set<Integer>> graph = new HashMap<>();
        for (int i = 1; i <= n; i++) {
            graph.put(i, new HashSet<>());
        }

        Arrays.stream(edges).forEach(edge -> {
            int u = edge[0];
            int v = edge[1];
            graph.get(u).add(v);
            graph.get(v).add(u);
            degree[u]++;
            degree[v]++;
        });

        List<Integer> oddNodes = Arrays.stream(degree)
            .filter(deg -> deg % 2 == 1)
            .boxed()
            .collect(Collectors.toList());

        int oddCount = oddNodes.size();
        if (oddCount == 0) {
            return true;
        } else if (oddCount == 2) {
            return oddNodes.stream().anyMatch(u ->
                graph.keySet().stream().noneMatch(v ->
                    oddNodes.contains(v) || graph.get(u).contains(v)
                )
            );
        } else if (oddCount == 4) {
            Integer[] oddArray = oddNodes.toArray(new Integer[0]);
            return (!graph.get(oddArray[0]).contains(oddArray[1]) && !graph.get(oddArray[2]).contains(oddArray[3])) ||
                   (!graph.get(oddArray[0]).contains(oddArray[2]) && !graph.get(oddArray[1]).contains(oddArray[3])) ||
                   (!graph.get(oddArray[0]).contains(oddArray[3]) && !graph.get(oddArray[1]).contains(oddArray[2]));
        } else {
            return false;
        }
    }
}

解释

方法:

这个题解的思路是首先统计每个节点的度数,然后根据度数的奇偶性来判断是否可以通过添加边使得所有节点的度数都变为偶数。具体来说,如果某个节点的度数等于n-1且为奇数,则无法通过添加边使其变为偶数,直接返回False。然后将所有度数为奇数的节点收集起来,如果奇数节点的个数大于4或为奇数,则无法通过添加边使得所有节点的度数都变为偶数,返回False。如果没有奇数节点,则不需要添加边,返回True。如果有两个奇数节点,检查是否可以通过添加一条边使得这两个节点的度数都变为偶数。如果有四个奇数节点,检查是否可以通过添加两条边使得这四个节点的度数都变为偶数。

时间复杂度:

O(m+n)

空间复杂度:

O(n)

代码细节讲解

🦆
在题解中,如果节点的度数为n-1且为奇数就返回False,这种处理方式的原因是什么?
在一个有n个节点的图中,若某个节点的度数为n-1且为奇数时,表示该节点与图中其他所有节点都有连接。因为图中共有n个节点,去除自身后,与该节点连接的节点数为n-1,如果n-1是奇数,则n必然是偶数。为了使该节点的度数变为偶数,需要再添加一个边连接该节点,但是已经与所有其他节点连通,无法增加新的边。因此,无法通过添加边使其度数变为偶数,所以返回False。
🦆
题解里提到,如果奇数节点的个数大于4或为奇数,则无法通过添加边使所有节点度数变为偶数。为什么是这样的规则?
每添加一条边,会影响两个节点的度数。因此,添加边只能改变两个节点的度数奇偶性。如果奇数节点的总数为奇数,则无论如何添加边,都会剩下至少一个奇数度数的节点,因为每次操作改变的是两个节点的状态。如果奇数节点大于4,虽然可以通过多次添加边改变奇偶性,但处理和确保最终所有节点度数都为偶数的复杂性和可能性会随着奇数节点数量的增加而降低。通常情况下,如果奇数节点数量超过4,要通过多步骤的边添加来平衡度数会变得复杂和不切实际。
🦆
对于有两个奇数度数的节点,题解考虑了直接连接它们,如果已存在边则尝试通过第三个节点连接。这种方法可能会有哪些潜在问题或限制?
尽管直接连接两个奇数度数的节点是解决问题的简单有效方法,但当这两个节点之间已经存在边时,直接连接不会改变它们的度数奇偶性。此外,尝试通过第三个节点连接这两个奇数节点意味着需要找到两个不与这两个奇数节点相连的其他节点,这可能在密集连接的图中不可行。如果大部分节点都已高度连接,找到这样的第三个节点会很困难,限制了这种方法的适用性。
🦆
题解尝试通过添加两条边来解决四个奇数度数节点的情况,但只考虑了一种特定的两两配对方式。是否存在其他有效的配对方式,这样的配对对算法是否有影响?
题解中考虑的是一种特定的配对方式,即首先选择一个节点与其他三个中的一个进行配对,然后将剩下的两个节点配对。虽然这种方法可能有效,但存在其他配对可能性,如完全不同的两两配对方案,可能会在某些情况下更有效或简单。未考虑所有可能的配对方式可能导致某些可行的解决方案被忽略。此外,算法的效率和简洁性可能因为需要检查多种配对方式而受到影响,增加了算法的复杂度和运行时间。

相关问题