这道题目来自华为OD(Outstanding Developer)机考中的双机位C卷,主要考察应聘者在多语言环境下解决实际网络问题的能力。题目要求考生在给定的二维矩阵中,找出所有相连的服务器(用1表示)组成的网络区域,并返回最大区域的服务器数量。
在实际网络运维和分布式系统设计中,这种"岛屿问题"的变种非常常见。比如数据中心需要实时监控服务器集群的连接状态,云计算平台要评估虚拟机组的容灾能力,都需要类似算法作为基础支撑。
题目可以抽象为经典的"岛屿问题"(Island Problem):
针对这类矩阵连通性问题,主要有三种解决方案:
深度优先搜索(DFS)
广度优先搜索(BFS)
并查集(Union-Find)
对于机考场景,推荐使用DFS或BFS,因为:
java复制public class ServerNetwork {
public int maxNetwork(int[][] grid) {
if (grid == null || grid.length == 0) return 0;
int max = 0;
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[0].length; j++) {
if (grid[i][j] == 1) {
max = Math.max(max, dfs(grid, i, j));
}
}
}
return max;
}
private int dfs(int[][] grid, int i, int j) {
if (i < 0 || i >= grid.length || j < 0 || j >= grid[0].length || grid[i][j] != 1) {
return 0;
}
grid[i][j] = 0; // 标记为已访问
return 1 + dfs(grid, i+1, j) + dfs(grid, i-1, j)
+ dfs(grid, i, j+1) + dfs(grid, i, j-1);
}
}
关键点说明:
python复制def max_network(grid):
if not grid:
return 0
max_area = 0
rows, cols = len(grid), len(grid[0])
def dfs(r, c):
if 0 <= r < rows and 0 <= c < cols and grid[r][c] == 1:
grid[r][c] = 0 # 标记为已访问
return 1 + dfs(r+1, c) + dfs(r-1, c) + dfs(r, c+1) + dfs(r, c-1)
return 0
for r in range(rows):
for c in range(cols):
if grid[r][c] == 1:
max_area = max(max_area, dfs(r, c))
return max_area
Python实现特点:
javascript复制function maxNetwork(grid) {
if (!grid || grid.length === 0) return 0;
let max = 0;
const rows = grid.length, cols = grid[0].length;
function dfs(i, j) {
if (i < 0 || i >= rows || j < 0 || j >= cols || grid[i][j] !== 1) {
return 0;
}
grid[i][j] = 0;
return 1 + dfs(i+1, j) + dfs(i-1, j) + dfs(i, j+1) + dfs(i, j-1);
}
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; j++) {
if (grid[i][j] === 1) {
max = Math.max(max, dfs(i, j));
}
}
}
return max;
}
注意事项:
go复制func maxNetwork(grid [][]int) int {
if len(grid) == 0 {
return 0
}
max := 0
rows, cols := len(grid), len(grid[0])
var dfs func(int, int) int
dfs = func(i, j int) int {
if i < 0 || i >= rows || j < 0 || j >= cols || grid[i][j] != 1 {
return 0
}
grid[i][j] = 0
return 1 + dfs(i+1, j) + dfs(i-1, j) + dfs(i, j+1) + dfs(i, j-1)
}
for i := 0; i < rows; i++ {
for j := 0; j < cols; j++ {
if grid[i][j] == 1 {
area := dfs(i, j)
if area > max {
max = area
}
}
}
}
return max
}
Go语言特性:
cpp复制#include <vector>
#include <algorithm>
using namespace std;
class Solution {
public:
int maxNetwork(vector<vector<int>>& grid) {
if (grid.empty()) return 0;
int max_area = 0;
for (int i = 0; i < grid.size(); ++i) {
for (int j = 0; j < grid[0].size(); ++j) {
if (grid[i][j] == 1) {
max_area = max(max_area, dfs(grid, i, j));
}
}
}
return max_area;
}
private:
int dfs(vector<vector<int>>& grid, int i, int j) {
if (i < 0 || i >= grid.size() || j < 0 || j >= grid[0].size() || grid[i][j] != 1) {
return 0;
}
grid[i][j] = 0;
return 1 + dfs(grid, i+1, j) + dfs(grid, i-1, j) + dfs(grid, i, j+1) + dfs(grid, i, j-1);
}
};
C++注意事项:
c复制int dfs(int** grid, int gridSize, int* gridColSize, int i, int j) {
if (i < 0 || i >= gridSize || j < 0 || j >= gridColSize[i] || grid[i][j] != 1) {
return 0;
}
grid[i][j] = 0;
return 1 + dfs(grid, gridSize, gridColSize, i+1, j)
+ dfs(grid, gridSize, gridColSize, i-1, j)
+ dfs(grid, gridSize, gridColSize, i, j+1)
+ dfs(grid, gridSize, gridColSize, i, j-1);
}
int maxNetwork(int** grid, int gridSize, int* gridColSize) {
if (gridSize == 0) return 0;
int max = 0;
for (int i = 0; i < gridSize; i++) {
for (int j = 0; j < gridColSize[i]; j++) {
if (grid[i][j] == 1) {
int area = dfs(grid, gridSize, gridColSize, i, j);
if (area > max) {
max = area;
}
}
}
}
return max;
}
C语言特点:
迭代代替递归:使用栈实现DFS可以避免递归深度限制
python复制def dfs_iterative(grid, i, j):
stack = [(i, j)]
area = 0
while stack:
r, c = stack.pop()
if 0 <= r < len(grid) and 0 <= c < len(grid[0]) and grid[r][c] == 1:
grid[r][c] = 0
area += 1
stack.extend([(r+1, c), (r-1, c), (r, c+1), (r, c-1)])
return area
方向数组简化代码:
java复制int[][] dirs = {{1,0},{-1,0},{0,1},{0,-1}};
for (int[] dir : dirs) {
int x = i + dir[0], y = j + dir[1];
// 处理四个方向
}
原地修改优化空间:利用输入矩阵记录访问状态
python复制test_cases = [
([], 0), # 空矩阵
([[0,0,0],[0,0,0]], 0), # 无服务器
([[1,1,1],[1,1,1]], 6), # 全连接
([[1,0,1],[0,1,0]], 1), # 最大区域为1
([[1,1,0,0],[0,1,1,0],[0,0,1,0],[1,0,0,0]], 5) # 复杂案例
]
提示:在真实面试中,除了写出正确代码,还应该能够分析时间/空间复杂度,讨论各种边界情况,并思考实际应用场景。