Score After Flipping Matrix
Problem
You are given an m x n binary matrix grid.
A move consists of choosing any row or column and toggling each value in that row or column (i.e., changing all 0's to 1's, and all 1's to 0's).
Every row of the matrix is interpreted as a binary number, and the score of the matrix is the sum of these numbers.
Return the highest possible score after making any number of moves (including zero moves).
Examples
Example 1:
Input: grid = [[0,0,1,1],[1,0,1,0],[1,1,0,0]]
Output: 39
Explanation: 0b1111 + 0b1001 + 0b1111 = 15 + 9 + 15 = 39
Example 2:
Input: grid = [[0]]
Output: 1
Solution
This is a greedy problem. Please refer the video explanation here: <div class="youtube-embed"><iframe src="https://www.youtube.com/embed/3NEPh2VV0wo" frameborder="0" allowfullscreen></iframe></div>
Method 1 - Multi-pass Solution
We know that the number is bigger when it has 1 in the most significant bit. For eg. 0b10 > 0b01.
Now, that we fixed the order in rows, we can flip as many 0s as possible in columns. So, we can do following:
- Flip all rows that start with zero;
- Flip all columns where the number of zeros is larger than the number of ones;
Code
Java
public int matrixScore(int[][] grid) {
int m = grid.length, n = grid[0].length;
for (int i = 0; i < m; i++) {
if (grid[i][0] == 0) {
flipRow(grid, i);
}
}
// we start with j = 1, as j = 0 is
// taken care off in previous loop
for (int j = 1; j < n; j++) {
int colSum = 0;
for (int i = 0; i < m; i++) {
colSum += grid[i][j];
}
if (colSum * 2 < m) {
flipCol(grid, j);
}
}
int sum = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
sum += grid[i][j] * (1 << (n - 1 - j));
}
}
return sum;
}
private void flipRow(int[][] grid, int r) {
for (int j = 0; j < grid[r].length; j++) {
grid[r][j] ^= 1;
}
}
private void flipCol(int[][] grid, int c) {
for (int i = 0; i < grid.length; i++) {
grid[i][c] ^= 1;
}
}
Complexity
- ⏰ Time complexity:
O(m*n) - 🧺 Space complexity:
O(1)
Method 2 - Without Flipping
We can build on previous solution, and reduce the number of loops.
- Initialise
ansto(1<<(n-1))*mas all 0th columns are flipped to 1 - Now traverse in each column and count number of
1s. - If
a[i][j] == a[i][0]then we can saya[i][j]will be 1 why??- If
a[i][0] == 0thena[i][j]will flipped so it will become 1 if its initial value is 0 so it satisfies our condition - If
a[i][0] == 1thena[i][j]wont change so if it is 1 then it will be 1
- If
- We can use above to find 1s in every column and decide whether to flip that column if number of 1s is exceeding 0
Code
Java
public int matrixScore(int[][] grid) {
int m = grid.length, n = grid[0].length;
int ans = (1 << (n - 1)) * m;
for (int j = 1; j < n; j++) {
int colSum = 0;
for (int i = 0; i < m; i++) {
if (grid[i][j] == grid[i][0]) {
colSum++;
}
}
ans += (1 << (n - 1 - j)) * Math.max(colSum, m - colSum);
}
return ans;
}
Complexity
- ⏰ Time complexity:
O(m*n) - 🧺 Space complexity:
O(1)