3240. Minimum Number of Flips to Make Binary Grid Palindromic II
Problem Description
You have an m x n
binary matrix grid
containing only 0s and 1s.
A row is palindromic if it reads the same from left to right as it does from right to left. Similarly, a column is palindromic if it reads the same from top to bottom as it does from bottom to top.
You can flip any cell in the grid, changing a 0
to 1
or a 1
to 0
.
Your goal is to find the minimum number of flips needed to satisfy both of these conditions:
- Every row in the grid must be palindromic
- Every column in the grid must be palindromic
- The total count of
1
s in the entire grid must be divisible by4
The problem asks you to return this minimum number of flips required.
For example, if you have a grid where some rows or columns are not palindromic, you need to flip certain cells to make them palindromic. Additionally, after all flips are done, the total number of 1
s in the grid must be a multiple of 4 (like 0, 4, 8, 12, etc.).
Intuition
Let's think about what happens when both rows and columns need to be palindromic simultaneously.
For any position (i, j)
in the grid, if row i
is palindromic, then grid[i][j]
must equal grid[i][n-j-1]
. Similarly, if column j
is palindromic, then grid[i][j]
must equal grid[m-i-1][j]
.
But here's the key insight: these constraints create groups of 4 cells that must all have the same value! Consider the four positions:
(i, j)
(i, n-j-1)
(m-i-1, j)
(m-i-1, n-j-1)
Due to the palindrome constraints:
grid[i][j]
must equalgrid[i][n-j-1]
(rowi
is palindromic)grid[m-i-1][j]
must equalgrid[m-i-1][n-j-1]
(rowm-i-1
is palindromic)grid[i][j]
must equalgrid[m-i-1][j]
(columnj
is palindromic)grid[i][n-j-1]
must equalgrid[m-i-1][n-j-1]
(columnn-j-1
is palindromic)
This means all four cells must be equal! So we can process the grid in groups of 4 symmetric cells. For each group, we count how many are currently 1
s and decide whether it's cheaper to flip them all to 0
or all to 1
.
The tricky part comes with odd dimensions. When m
or n
is odd, we have middle rows or columns that don't form complete 4-cell groups:
-
If both
m
andn
are odd, there's a center cell that maps to itself under both reflections. Since the total number of1
s must be divisible by 4, and all other cells come in groups of 2 or 4, this center cell must be0
. -
If only one dimension is odd, we have pairs of cells in the middle row/column that must be equal due to palindrome constraints. Here's where it gets interesting: these pairs contribute either 0 or 2 to the count of
1
s.
To satisfy the divisibility by 4 requirement, we need to be careful about how many pairs contribute 2 (i.e., both cells are 1
). If we already have an even number of such pairs, we're good. But if we have an odd number of pairs contributing 2 (making the total count 2 mod 4
), we need to either:
- Change one differing pair to both be
1
s (if such pairs exist) - Or change one matching pair of
1
s to0
s (if no differing pairs exist)
This ensures the final count of 1
s is divisible by 4 while minimizing flips.
Learn more about Two Pointers patterns.
Solution Approach
Let's walk through the implementation step by step:
Step 1: Process 4-cell groups
We iterate through the top-left quadrant of the grid using i in range(m // 2)
and j in range(n // 2)
. For each position (i, j)
, we identify its three symmetric counterparts:
(x, j)
wherex = m - i - 1
(vertically symmetric)(i, y)
wherey = n - j - 1
(horizontally symmetric)(x, y)
(diagonally symmetric)
We count how many of these 4 cells are currently 1
:
cnt1 = grid[i][j] + grid[x][j] + grid[i][y] + grid[x][y]
To make all 4 cells the same, we can either:
- Flip
cnt1
cells to make them all0
- Flip
4 - cnt1
cells to make them all1
We choose the minimum: min(cnt1, 4 - cnt1)
and add it to our answer.
Step 2: Handle the center cell (if both dimensions are odd)
If both m
and n
are odd, there's a center cell at (m // 2, n // 2)
. Since all other cells come in groups of 2 or 4, and the total must be divisible by 4, this center cell must be 0
. If it's currently 1
, we need one flip:
if m % 2 and n % 2: ans += grid[m // 2][n // 2]
Step 3: Handle middle row/column
Initialize diff = 0
to count pairs that differ, and cnt1 = 0
to count the number of 1
s from matching pairs.
If m
is odd (middle row exists):
for j in range(n // 2):
if grid[m // 2][j] == grid[m // 2][n - j - 1]:
cnt1 += grid[m // 2][j] * 2 # Add 2 if both are 1, 0 if both are 0
else:
diff += 1 # Count differing pairs
Similarly, if n
is odd (middle column exists):
for i in range(m // 2):
if grid[i][n // 2] == grid[m - i - 1][n // 2]:
cnt1 += grid[i][n // 2] * 2
else:
diff += 1
Step 4: Determine additional flips needed
Now we need to ensure the total count of 1
s is divisible by 4:
-
If
cnt1 % 4 == 0
: The count is already good. We just need to fix thediff
differing pairs by making them match (doesn't matter if they become 0 or 1), requiringdiff
flips. -
If
cnt1 % 4 == 2
: We have an issue.- If
diff > 0
: We can fix one differing pair by making both cells1
, adding 2 to our count (making it divisible by 4), and fix the remainingdiff - 1
pairs however we want. Total:diff
flips. - If
diff == 0
: All pairs already match, but we have the wrong count. We need to flip one matching pair of1
s to0
s, requiring2
flips.
- If
This is elegantly captured in the expression:
ans += diff if cnt1 % 4 == 0 or diff else 2
The condition evaluates to diff
when either cnt1 % 4 == 0
or diff > 0
, and 2
when cnt1 % 4 != 0
and diff == 0
.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a concrete example to illustrate the solution approach.
Consider this 3Γ4 grid:
1 0 0 1 0 1 1 0 1 1 0 0
Step 1: Process 4-cell groups
Since m=3 and n=4, we iterate through i β [0,1) and j β [0,2).
For position (0, 0):
- The 4 symmetric cells are: (0,0), (0,3), (2,0), (2,3)
- Their values: 1, 1, 1, 0
- Count of 1s: 3
- To make them all equal: min(3, 4-3) = 1 flip needed
- We flip (2,3) from 0β1 to make all four cells equal to 1
For position (0, 1):
- The 4 symmetric cells are: (0,1), (0,2), (2,1), (2,2)
- Their values: 0, 0, 1, 0
- Count of 1s: 1
- To make them all equal: min(1, 4-1) = 1 flip needed
- We flip (2,1) from 1β0 to make all four cells equal to 0
After Step 1, our grid becomes:
1 0 0 1 0 1 1 0 (middle row - unchanged so far) 1 0 0 1
Total flips so far: 2
Step 2: Check center cell
Since m=3 (odd) but n=4 (even), there's no single center cell. Skip this step.
Step 3: Handle middle row
Since m=3 is odd, we have a middle row at index 1. We check pairs:
-
Pair (1,0) and (1,3): values are 0 and 0 β they match
- cnt1 += 0Γ2 = 0
-
Pair (1,1) and (1,2): values are 1 and 1 β they match
- cnt1 += 1Γ2 = 2
So diff = 0 (no differing pairs) and cnt1 = 2
Step 4: Determine additional flips
We have cnt1 = 2, which means cnt1 % 4 = 2 (not divisible by 4).
Since cnt1 % 4 β 0 and diff = 0, we need 2 additional flips. We must flip one matching pair to fix the divisibility issue. Let's flip the pair (1,1) and (1,2) from 1β0:
Final grid:
1 0 0 1 0 0 0 0 1 0 0 1
Let's verify:
- All rows are palindromic: β
- All columns are palindromic: β
- Total 1s: 4 (divisible by 4) β
Total minimum flips: 2 + 2 = 4
This example demonstrates how the algorithm:
- First handles groups of 4 symmetric cells
- Then addresses the middle row/column palindrome constraints
- Finally ensures the total count of 1s is divisible by 4
Solution Implementation
1class Solution:
2 def minFlips(self, grid: List[List[int]]) -> int:
3 rows, cols = len(grid), len(grid[0])
4 total_flips = 0
5
6 # Process each group of 4 symmetric cells (corners of rectangles)
7 for row in range(rows // 2):
8 for col in range(cols // 2):
9 # Find the symmetric positions
10 sym_row = rows - row - 1
11 sym_col = cols - col - 1
12
13 # Count ones in the group of 4 symmetric cells
14 ones_count = (grid[row][col] +
15 grid[sym_row][col] +
16 grid[row][sym_col] +
17 grid[sym_row][sym_col])
18
19 # Minimum flips needed to make all 4 cells equal
20 # Either make all 0s or all 1s, whichever requires fewer flips
21 total_flips += min(ones_count, 4 - ones_count)
22
23 # Handle center cell if both dimensions are odd
24 if rows % 2 == 1 and cols % 2 == 1:
25 total_flips += grid[rows // 2][cols // 2]
26
27 # Handle middle row and column for palindrome property
28 mismatched_pairs = 0
29 paired_ones_count = 0
30
31 # Process middle row if grid has odd number of rows
32 if rows % 2 == 1:
33 for col in range(cols // 2):
34 left_val = grid[rows // 2][col]
35 right_val = grid[rows // 2][cols - col - 1]
36
37 if left_val == right_val:
38 # Count paired ones (both cells are 1)
39 paired_ones_count += left_val * 2
40 else:
41 # Count mismatched pairs
42 mismatched_pairs += 1
43
44 # Process middle column if grid has odd number of columns
45 if cols % 2 == 1:
46 for row in range(rows // 2):
47 top_val = grid[row][cols // 2]
48 bottom_val = grid[rows - row - 1][cols // 2]
49
50 if top_val == bottom_val:
51 # Count paired ones (both cells are 1)
52 paired_ones_count += top_val * 2
53 else:
54 # Count mismatched pairs
55 mismatched_pairs += 1
56
57 # Adjust flips based on divisibility by 4 requirement
58 # If paired ones are divisible by 4 or we have mismatched pairs,
59 # add the mismatched pairs count; otherwise add 2
60 if paired_ones_count % 4 == 0 or mismatched_pairs > 0:
61 total_flips += mismatched_pairs
62 else:
63 total_flips += 2
64
65 return total_flips
66
1class Solution {
2 public int minFlips(int[][] grid) {
3 int rows = grid.length;
4 int cols = grid[0].length;
5 int totalFlips = 0;
6
7 // Process the 4-symmetric quadrants (corners that mirror across both axes)
8 for (int i = 0; i < rows / 2; i++) {
9 for (int j = 0; j < cols / 2; j++) {
10 // Calculate positions of the 4 symmetric cells
11 int mirrorRow = rows - i - 1;
12 int mirrorCol = cols - j - 1;
13
14 // Count number of 1s among the 4 symmetric positions
15 int onesCount = grid[i][j] + grid[mirrorRow][j] +
16 grid[i][mirrorCol] + grid[mirrorRow][mirrorCol];
17
18 // Choose minimum flips: either flip all 1s to 0 or all 0s to 1
19 totalFlips += Math.min(onesCount, 4 - onesCount);
20 }
21 }
22
23 // Handle the center cell if both dimensions are odd
24 if (rows % 2 == 1 && cols % 2 == 1) {
25 // Center cell must be 0 for palindrome property
26 totalFlips += grid[rows / 2][cols / 2];
27 }
28
29 int mismatchCount = 0; // Count of mismatched pairs in middle row/column
30 int pairedOnesCount = 0; // Count of 1s in matched pairs
31
32 // Process middle row if number of rows is odd
33 if (rows % 2 == 1) {
34 int middleRow = rows / 2;
35 for (int j = 0; j < cols / 2; j++) {
36 int mirrorCol = cols - j - 1;
37
38 if (grid[middleRow][j] == grid[middleRow][mirrorCol]) {
39 // If pair matches and both are 1s, add 2 to count
40 pairedOnesCount += grid[middleRow][j] * 2;
41 } else {
42 // Pair doesn't match, needs one flip
43 mismatchCount++;
44 }
45 }
46 }
47
48 // Process middle column if number of columns is odd
49 if (cols % 2 == 1) {
50 int middleCol = cols / 2;
51 for (int i = 0; i < rows / 2; i++) {
52 int mirrorRow = rows - i - 1;
53
54 if (grid[i][middleCol] == grid[mirrorRow][middleCol]) {
55 // If pair matches and both are 1s, add 2 to count
56 pairedOnesCount += grid[i][middleCol] * 2;
57 } else {
58 // Pair doesn't match, needs one flip
59 mismatchCount++;
60 }
61 }
62 }
63
64 // Adjust flips based on divisibility by 4 constraint
65 // If pairedOnesCount is divisible by 4 or we have mismatches, use mismatchCount
66 // Otherwise, we need 2 additional flips to maintain divisibility
67 totalFlips += (pairedOnesCount % 4 == 0 || mismatchCount > 0) ? mismatchCount : 2;
68
69 return totalFlips;
70 }
71}
72
1class Solution {
2public:
3 int minFlips(vector<vector<int>>& grid) {
4 int rows = grid.size();
5 int cols = grid[0].size();
6 int totalFlips = 0;
7
8 // Process all 4-symmetric groups (corners that must be equal)
9 // Each group consists of 4 cells: (i,j), (i,n-1-j), (m-1-i,j), (m-1-i,n-1-j)
10 for (int i = 0; i < rows / 2; ++i) {
11 for (int j = 0; j < cols / 2; ++j) {
12 int mirrorRow = rows - i - 1;
13 int mirrorCol = cols - j - 1;
14
15 // Count number of 1s in the 4-cell group
16 int onesCount = grid[i][j] + grid[mirrorRow][j] +
17 grid[i][mirrorCol] + grid[mirrorRow][mirrorCol];
18
19 // Choose minimum flips: either make all 0s or all 1s
20 totalFlips += min(onesCount, 4 - onesCount);
21 }
22 }
23
24 // Handle center cell if both dimensions are odd
25 if (rows % 2 == 1 && cols % 2 == 1) {
26 // Center cell must be 0 for palindrome property
27 totalFlips += grid[rows / 2][cols / 2];
28 }
29
30 int mismatchPairs = 0; // Count of mismatched symmetric pairs
31 int matchedOnes = 0; // Count of 1s in matched symmetric pairs
32
33 // Process middle row if number of rows is odd
34 if (rows % 2 == 1) {
35 int middleRow = rows / 2;
36 for (int j = 0; j < cols / 2; ++j) {
37 int mirrorCol = cols - j - 1;
38
39 if (grid[middleRow][j] == grid[middleRow][mirrorCol]) {
40 // If pair matches and both are 1s, count them
41 matchedOnes += grid[middleRow][j] * 2;
42 } else {
43 // Count mismatched pairs
44 mismatchPairs += 1;
45 }
46 }
47 }
48
49 // Process middle column if number of columns is odd
50 if (cols % 2 == 1) {
51 int middleCol = cols / 2;
52 for (int i = 0; i < rows / 2; ++i) {
53 int mirrorRow = rows - i - 1;
54
55 if (grid[i][middleCol] == grid[mirrorRow][middleCol]) {
56 // If pair matches and both are 1s, count them
57 matchedOnes += grid[i][middleCol] * 2;
58 } else {
59 // Count mismatched pairs
60 mismatchPairs += 1;
61 }
62 }
63 }
64
65 // Handle the special case for middle row/column
66 // If matchedOnes is not divisible by 4 and no mismatched pairs exist,
67 // we need to flip 2 matched 1s to maintain divisibility by 4
68 totalFlips += (matchedOnes % 4 == 0 || mismatchPairs > 0) ? mismatchPairs : 2;
69
70 return totalFlips;
71 }
72};
73
1/**
2 * Calculates minimum flips needed to make a grid palindromic in both directions
3 * with the number of 1s divisible by 4
4 * @param grid - 2D binary grid
5 * @returns minimum number of flips required
6 */
7function minFlips(grid: number[][]): number {
8 const rows: number = grid.length;
9 const cols: number = grid[0].length;
10 let totalFlips: number = 0;
11
12 // Process each quadrant (4 symmetric positions)
13 // For positions that mirror across both axes
14 for (let row = 0; row < Math.floor(rows / 2); row++) {
15 for (let col = 0; col < Math.floor(cols / 2); col++) {
16 // Calculate symmetric positions
17 const mirrorRow: number = rows - row - 1;
18 const mirrorCol: number = cols - col - 1;
19
20 // Count number of 1s in the four symmetric positions
21 const onesCount: number = grid[row][col] + grid[mirrorRow][col] +
22 grid[row][mirrorCol] + grid[mirrorRow][mirrorCol];
23
24 // Choose minimum flips: either make all 0s or all 1s
25 totalFlips += Math.min(onesCount, 4 - onesCount);
26 }
27 }
28
29 // Handle center cell if both dimensions are odd
30 if (rows % 2 === 1 && cols % 2 === 1) {
31 // Center cell must be 0 for divisibility by 4
32 totalFlips += grid[Math.floor(rows / 2)][Math.floor(cols / 2)];
33 }
34
35 let mismatchPairs: number = 0; // Count of mismatched symmetric pairs
36 let matchedOnes: number = 0; // Count of 1s in matched pairs
37
38 // Process middle row if grid has odd number of rows
39 if (rows % 2 === 1) {
40 const middleRow: number = Math.floor(rows / 2);
41
42 for (let col = 0; col < Math.floor(cols / 2); col++) {
43 const mirrorCol: number = cols - col - 1;
44
45 if (grid[middleRow][col] === grid[middleRow][mirrorCol]) {
46 // If pair matches, count the 1s (multiply by 2 for both positions)
47 matchedOnes += grid[middleRow][col] * 2;
48 } else {
49 // If pair doesn't match, we need to flip one
50 mismatchPairs += 1;
51 }
52 }
53 }
54
55 // Process middle column if grid has odd number of columns
56 if (cols % 2 === 1) {
57 const middleCol: number = Math.floor(cols / 2);
58
59 for (let row = 0; row < Math.floor(rows / 2); row++) {
60 const mirrorRow: number = rows - row - 1;
61
62 if (grid[row][middleCol] === grid[mirrorRow][middleCol]) {
63 // If pair matches, count the 1s (multiply by 2 for both positions)
64 matchedOnes += grid[row][middleCol] * 2;
65 } else {
66 // If pair doesn't match, we need to flip one
67 mismatchPairs += 1;
68 }
69 }
70 }
71
72 // Adjust flips to ensure total 1s is divisible by 4
73 // If matched 1s already divisible by 4 or we have mismatches to fix, use mismatch count
74 // Otherwise, need to flip 2 more matched 1s to 0s
75 totalFlips += (matchedOnes % 4 === 0 || mismatchPairs > 0) ? mismatchPairs : 2;
76
77 return totalFlips;
78}
79
Time and Space Complexity
Time Complexity: O(m Γ n)
The algorithm iterates through the grid in the following manner:
- The first nested loop iterates through
(m // 2) Γ (n // 2)
elements, processing each quadrant's corresponding four cells, which takesO(m Γ n / 4)
time. - If
m
is odd, it processes the middle row withn // 2
iterations, takingO(n / 2)
time. - If
n
is odd, it processes the middle column withm // 2
iterations, takingO(m / 2)
time. - The center cell (if both
m
andn
are odd) is processed inO(1)
time.
The total time is O(m Γ n / 4) + O(n / 2) + O(m / 2) + O(1)
, which simplifies to O(m Γ n)
since we visit each cell of the grid at most once.
Space Complexity: O(1)
The algorithm uses only a constant amount of extra space with variables ans
, i
, j
, x
, y
, cnt1
, and diff
. No additional data structures that scale with input size are created, resulting in constant space complexity.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Incorrectly Handling the Middle Row/Column Palindrome Requirement
Pitfall: A common mistake is forgetting that when processing middle rows or columns, we need to ensure they are palindromic while also maintaining the divisibility by 4 constraint. Many solutions incorrectly assume that simply making pairs match is sufficient.
Example of the mistake:
# WRONG: Just counting flips to make pairs match
if rows % 2 == 1:
for col in range(cols // 2):
if grid[rows // 2][col] != grid[rows // 2][cols - col - 1]:
total_flips += 1 # This ignores the divisibility constraint!
Solution: Track both mismatched pairs AND the count of 1s from matched pairs. This allows us to make intelligent decisions about whether to flip pairs to 0s or 1s to satisfy the divisibility by 4 requirement.
2. Misunderstanding the Center Cell Logic
Pitfall: When both dimensions are odd, the center cell must always be 0 for the total count to be divisible by 4. A common error is trying to include this cell in complex calculations or forgetting about it entirely.
Example of the mistake:
# WRONG: Trying to be clever with the center cell if rows % 2 and cols % 2: center = grid[rows // 2][cols // 2] if (total_ones + center) % 4 != 0: # Overcomplicated and wrong! total_flips += 1
Solution: Simply check if the center cell is 1. If it is, flip it to 0. The logic is straightforward: total_flips += grid[rows // 2][cols // 2]
3. Off-by-One Errors in Symmetric Position Calculations
Pitfall: Calculating symmetric positions incorrectly, especially when dealing with 0-indexed arrays.
Example of the mistake:
# WRONG: Incorrect symmetric position sym_row = rows - row # Should be rows - row - 1 sym_col = cols - col # Should be cols - col - 1
Solution: Always use rows - row - 1
and cols - col - 1
for finding symmetric positions in 0-indexed arrays. Test with small examples to verify correctness.
4. Incorrect Final Adjustment Logic
Pitfall: The final adjustment for divisibility by 4 is subtle. The condition paired_ones_count % 4 == 0 or mismatched_pairs > 0
might seem arbitrary but is crucial.
Example of the mistake:
# WRONG: Always adding mismatched_pairs total_flips += mismatched_pairs # Doesn't handle the case when we need to flip a matched pair
Solution: Understand the two cases:
- If
paired_ones_count % 4 == 2
andmismatched_pairs == 0
: We must flip one matched pair (2 flips) - Otherwise: We can fix mismatched pairs to adjust the count (mismatched_pairs flips)
5. Double-Counting Cells in Groups
Pitfall: When processing the 4-cell groups, middle rows, and middle columns, ensure cells aren't processed multiple times.
Example of the mistake:
# WRONG: Processing all rows and columns without considering overlap
for row in range(rows): # Should be range(rows // 2)
for col in range(cols): # Should be range(cols // 2)
Solution: Use range(rows // 2)
and range(cols // 2)
for the 4-cell groups, and carefully handle middle rows/columns separately to avoid overlap.
A heap is a ...?
Recommended Readings
Tech Interview Pattern Two Pointers Introduction If you prefer videos here's a super quick introduction to Two Pointers div class responsive iframe iframe src https www youtube com embed xZ4AfXHQ1VQ title YouTube video player frameborder 0 allow accelerometer autoplay clipboard write encrypted media gyroscope picture in picture allowfullscreen iframe div Two pointers is a common interview
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Want a Structured Path to Master System Design Too? Donβt Miss This!