861.翻转矩阵后的得分
描述
有一个二维矩阵 A
其中每个元素的值为 0
或 1
。
移动是指选择任一行或列,并转换该行或列中的每一个值:将所有 0
都更改为 1
,将所有 1
都更改为 0
。
在做出任意次数的移动后,将该矩阵的每一行都按照二进制数来解释,矩阵的得分就是这些数字的总和。
返回尽可能高的分数。
实例\
输入:[[0,0,1,1],[1,0,1,0],[1,1,0,0]]
输出:39
解释:
转换为 [[1,1,1,1],[1,0,0,1],[1,1,1,1]]
0b1111 + 0b1001 + 0b1111 = 15 + 9 + 15 = 39
提示
1 <= A.length <= 20
1 <= A[0].length <= 20
A[i][j]
是0
或1
题解
一个矩阵计算每一行的二进制之和,也就是每一列中权重都是相同的,那么只要尽可能让每一排的第一个元素是1
并且每一列中的1
尽可能多
- 检查每一行的开头,如果值为
0
就将这一行翻转 - 检查每一列中
1
和0
的个数,如果0
多就将这一列翻转
public static int matrixScore(int[][] A) {
int h = A.length;
int w = A[0].length;
int[] shuiPing = new int[h];//记录每一列中1的个数
int[] chuiZhi = new int[w];//记录每一排中1的个数
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
shuiPing[i] += A[i][j];
chuiZhi[j] += A[i][j];
}
}
boolean isChange = true;
while (isChange){
isChange = false;
for (int i = 0; i < w; i++) {
if (h-chuiZhi[i] > chuiZhi[i]){
for (int j = 0; j < h; j++) {
if ((A[j][i] == 1)) {
A[j][i] = 0;
shuiPing[j]--;
chuiZhi[i]--;
} else {
A[j][i] = 1;
shuiPing[j]++;
chuiZhi[i]++;
}
}
isChange = true;
}
}
for (int i = 0; i < h; i++) {
if (A[i][0] == 0){
for (int j = 0; j < w; j++) {
if ((A[i][j] == 1)) {
A[i][j] = 0;
shuiPing[i]--;
chuiZhi[j]--;
} else {
A[i][j] = 1;
shuiPing[i]++;
chuiZhi[j]++;
}
}
isChange = true;
}
}
}
int sum = 0;
for (int i = 0; i < h; i++) {
for (int j = 0; j < w; j++) {
sum += A[i][j] * Math.pow(2,w-j-1);
}
}
return sum;
}
查看范例代码看到一个更加精简的.
- 每一行的第一个元素都可以通过对列翻转将其变成
1
- 完成了上一步之后,每一列中
1
的数量可以通过翻转变成这一列中Math.max(num(0),num(1))
public int matrixScore(int[][] A) {
int m = A.length;
int n = A[0].length;
int sum = 0;
for(int i = 0; i < m; i++) {
if(A[i][0] == 0) {
for(int j = 0; j < n; j++) {
A[i][j] = 1 - A[i][j];
}
}
}
sum += m * (int)Math.pow(2, n - 1);
for(int j = 1; j < n; j++) {
int count = 0;
for(int i = 0; i < m; i++) {
if(A[i][j] == 1) {
count ++;
}
}
if(2 * count < m) {
count = m - count;
}
sum += count * (int)Math.pow(2, n - j - 1);
}
return sum;
}