1267. Count Servers that Communicate - Explanation
Description
You are given a map of a server center, represented as a m * n integer matrix grid, where 1 means that on that cell there is a server and 0 means that it is no server. Two servers are said to communicate if they are on the same row or on the same column.
Return the number of servers that communicate with any other server.
Example 1:
Input: grid = [
[1,1,0,0],
[0,0,1,0],
[0,0,1,0],
[0,0,0,1]
]
Output: 4Explanation: Except for the server at the position (3,3), all other servers have other servers to communicate.
Example 2:
Input: grid = [
[1,0],
[1,1]
]
Output: 3Explanation: All three servers can communicate with at least one other server.
Constraints:
1 <= grid.length, grid[i].length <= 250grid[i][j] == 0 or 1
Topics
Prerequisites
Before attempting this problem, you should be comfortable with:
- 2D Matrix Traversal - Iterating through rows and columns of a grid using nested loops
- Counting with Arrays - Using auxiliary arrays to track counts per row and column
- In-place Marking - Modifying grid values to mark visited or processed cells (for space-optimized solution)
1. Brute Force
Intuition
A server can communicate if there is at least one other server in the same row or column. For each server, we can directly check its entire row and column to see if any other server exists. If we find at least one, this server counts toward our result.
Algorithm
- Iterate through each cell in the grid.
- For each cell containing a server (value
1):- Check all other cells in the same row for another server.
- If not found in the row, check all other cells in the same column.
- If another server is found in either the row or column, increment the result.
- Return the total count of servers that can communicate.
class Solution:
def countServers(self, grid: List[List[int]]) -> int:
m, n = len(grid), len(grid[0])
res = 0
for r in range(m):
for c in range(n):
if grid[r][c] == 0:
continue
found = False
for col in range(n):
if col != c and grid[r][col] == 1:
found = True
break
if not found:
for row in range(m):
if row != r and grid[row][c] == 1:
found = True
break
if found:
res += 1
return resTime & Space Complexity
- Time complexity:
- Space complexity:
Where is the number of rows and is the number of columns of the given matrix .
2. Iteration
Intuition
Instead of checking each server's row and column individually, we can precompute the count of servers in each row and column. A server can communicate if there is more than one server in its row or more than one server in its column. This allows us to determine each server's status in constant time after the preprocessing step.
Algorithm
- Create two arrays:
row_cntto store server counts per row andcol_cntfor columns. - First pass: Count the number of servers in each row and column.
- Second pass: For each server, check if its row count or column count is greater than
1.- If yes, this server can communicate with at least one other server.
- Return the total count of communicating servers.
class Solution:
def countServers(self, grid: List[List[int]]) -> int:
ROWS, COLS = len(grid), len(grid[0])
row_cnt = [0] * ROWS
col_cnt = [0] * COLS
for r in range(ROWS):
for c in range(COLS):
if grid[r][c] == 1:
row_cnt[r] += 1
col_cnt[c] += 1
res = 0
for r in range(ROWS):
for c in range(COLS):
if grid[r][c] and max(row_cnt[r], col_cnt[c]) > 1:
res += 1
return resTime & Space Complexity
- Time complexity:
- Space complexity:
Where is the number of rows and is the number of columns of the given matrix .
3. Iteration (Space Optimized)
Intuition
We can avoid using extra arrays by processing rows and columns separately and using the grid itself to mark processed servers. First, we process all rows with multiple servers and mark those servers. Then, we process columns and only count unmarked servers in columns with multiple servers. The marking prevents double counting servers that belong to both a communicating row and column.
Algorithm
- Process rows first:
- For each row with more than one server, add all servers in that row to the result.
- Mark these servers by setting their value to
-1.
- Process columns:
- For each column, count total servers (using absolute values) and unmarked servers.
- If the column has two or more servers, add the count of unmarked servers to the result.
- Restore marked servers by setting
-1back to1.
- Return the total count.
class Solution:
def countServers(self, grid: List[List[int]]) -> int:
res = 0
ROWS, COLS = len(grid), len(grid[0])
# Rows
for r in range(ROWS):
row_sum = sum(grid[r])
if row_sum <= 1:
continue
res += row_sum
for c in range(COLS):
if grid[r][c]:
grid[r][c] = -1 # Mark
# Cols
for c in range(COLS):
col_sum = unmarked = 0
for r in range(ROWS):
col_sum += abs(grid[r][c])
if grid[r][c] > 0:
unmarked += 1
elif grid[r][c] < 0:
grid[r][c] = 1 # Unmark
if col_sum >= 2:
res += unmarked
return resTime & Space Complexity
- Time complexity:
- Space complexity:
Where is the number of rows and is the number of columns of the given matrix .
Common Pitfalls
Counting Total Servers Instead of Communicating Servers
A server only counts if it can communicate with at least one other server. Counting all servers (all cells with value 1) ignores the communication requirement.
Using OR Instead of Checking Both Row and Column Counts
A server communicates if its row has 2+ servers OR its column has 2+ servers. Using AND would incorrectly require both conditions.
# Wrong: requires both row AND column to have multiple servers
if row_cnt[r] > 1 and col_cnt[c] > 1:
# Correct: either condition is sufficient
if row_cnt[r] > 1 or col_cnt[c] > 1:Double Counting Servers
When processing rows and columns separately (in the space-optimized solution), servers that are in both a communicating row and a communicating column can be counted twice. Mark processed servers to avoid this.
Sign in to join the discussion