添加边使所有节点度数都为偶数
难度:
标签:
题目描述
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,这种处理方式的原因是什么?
▷🦆
题解里提到,如果奇数节点的个数大于4或为奇数,则无法通过添加边使所有节点度数变为偶数。为什么是这样的规则?
▷🦆
对于有两个奇数度数的节点,题解考虑了直接连接它们,如果已存在边则尝试通过第三个节点连接。这种方法可能会有哪些潜在问题或限制?
▷🦆
题解尝试通过添加两条边来解决四个奇数度数节点的情况,但只考虑了一种特定的两两配对方式。是否存在其他有效的配对方式,这样的配对对算法是否有影响?
▷