1284. Minimum Number of Flips to Convert Binary Matrix to Zero Matrix
BFS
T: O(m*n + 2^(m*n)), 1 <= m, n <= 3
S: 2^(m*n)
class Solution {
private static final int[][] DIRS = {{0,1}, {1,0}, {0,-1}, {-1,0}};
private record Step(int state, int level){};
public int minFlips(int[][] mat) {
int m = mat.length;
int n = mat[0].length;
int state = 0;
for (int i = m -1 ; i >= 0; i--) { // [0,0], [0,1] -> become 1000 -> 8
for (int j = n - 1; j >= 0; j--) {
state <<= 1; // left shift to have space
state |= mat[i][j]; // set value, so the first value will be in left side, but we start from end, so [0,0] will be in most right side
}
}
// System.out.println(state);
Set<Integer> visited = new HashSet<>();
Queue<Step> queue = new LinkedList<>();
queue.offer(new Step(state, 0));
while (!queue.isEmpty()) {
Step cur = queue.poll();
if (visited.contains(cur.state)) {
continue;
}
visited.add(cur.state);
if (cur.state == 0) {
return cur.level;
}
// try each cell to do flip
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
// flip this cell
int newState = cur.state;
int mask = 1 << (i*n + j); // move to that cell's position
newState ^= mask;
// then flip this cell's neights value
for (int[] dir: DIRS) {
int x = i + dir[0];
int y = j + dir[1];
if (x < 0 || x >= m || y < 0 || y >= n) {
continue;
}
mask = 1 << (x*n + y);
newState ^= mask;
}
// after flip values, go to next round
queue.offer(new Step(newState, cur.level+1));
}
}
}
return -1;
}
}
/**
state: 2^(m*n)
so
T: O(m*n + 2^(m*n)), 1 <= m, n <= 3
S: 2^(m*n)
*/
use bit
T: O((mn)^2)
S: O(mn)
class Solution {
public int minFlips(int[][] mat) {
int m = mat.length;
int n = mat[0].length;
int res = Integer.MAX_VALUE;
for (int state = 0; state < (1 << (m*n)); state++) { // state is bit representation(means flips ways)
if (check(mat, state)) {
res = Math.min(res, Integer.bitCount(state));
}
}
return res == Integer.MAX_VALUE ? - 1 : res;
}
private boolean check(int[][] mat, int state) {
int[][] dirs = {{0,1},{0,-1},{1,0},{-1,0},{0,0}};
int m = mat.length;
int n = mat[0].length;
int temp[][] = new int[m][n];
for (int i = 0; i < m; i++) { // clone() only for 1d array (deep copy)
temp[i] = mat[i].clone();
}
for (int b = 0; b < (m*n); b++) {
int doFlip = state%2;
state /= 2; // move to higher bit
if (doFlip == 0) {
continue;
}
int x = b/n;
int y = b%n;
for (int[] dir : dirs) {
int nextX = x + dir[0];
int nextY = y + dir[1];
if (!isVaild(m, n, nextX, nextY)) {
continue;
}
temp[nextX][nextY] = 1 - temp[nextX][nextY];
}
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (temp[i][j] != 0) {
return false;
}
}
}
return true;
}
private boolean isVaild(int m, int n, int x, int y) {
return x >= 0 && x < m && y >= 0 && y < n;
}
}
/*
1 <= m, n <= 3
3*3 matrix -> 9 elements
so the result is at most 2^9 = 512
use brute force:
so we can use bit to represent the all flip combinations
use these all flip combinations to flip (5 ways, include not flip) => T: O(mn)
if this combination can work, cal this combination's one, it's the flip numbers
find the min of (these flip numbers)
if it's a 2*2 matrix
ex:
[[0,0],[0,1]]
all flip combinations (是否要翻轉的所有方式)
can represent as
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101
1110
1111
2. check method()
so when we use one flip to check , at last check is the result all zero,
return true, if not return false
use one flip way to check
for all x, y cordination { // int b
ex:
for (b = 0, b < mn; b++) // mn also 4, => T: O(mn)
0010, means first one doesn't flip, so skip :
how to get lowest bits? (0010%2) is the lowest value of binary
(0010/2), move to higher next bit
001, means need to do flip
so check
int x = b/n
int y = b%n
check 5 dir
if (valid) {
make temp[newX][newY] = 1 - temp[newX][newY]
}
3.
at last check all temp value is all zero => T: O(mn)
T: O((mn)^2)
S: O(mn)
*/
Last updated