861. 翻转矩阵后的得分https://leetcode.cn/problems/score-after-flipping-matrix/
难度中等236
给你一个大小为 m x n
的二元矩阵 grid
,矩阵中每个元素的值为 0
或 1
。
一次 移动 是指选择任一行或列,并转换该行或列中的每一个值:将所有 0
都更改为 1
,将所有 1
都更改为 0
。
在做出任意次数的移动后,将该矩阵的每一行都按照二进制数来解释,矩阵的 得分 就是这些数字的总和。
在执行任意次 移动 后(含 0 次),返回可能的最高分数。
示例 1:
输入:grid = [[0,0,1,1],[1,0,1,0],[1,1,0,0]] 输出:39 解释:0b1111 + 0b1001 + 0b1111 = 15 + 9 + 15 = 39
示例 2:
输入:grid = [[0]] 输出:1
提示:
m == grid.length
n == grid[i].length
1 <= m, n <= 20
grid[i][j]
为0
或1
思考:
以十进制为例子,要想让一个数的数值更大,就要让其百千万位上的数字增加,二进制同理,在题目给出的二维数组中,通过将某一行或列的数据进行翻转来达到目的
进行一个这样的假设,有一个三行四列的二维数组:
对于行:
第一行:
如果第一个数为0,将它进行翻转,第一个数为1,不翻转
第二行:
如果第一个数为0,将它进行翻转,第一个数为1,不翻转
第三行:
如果第一个数为0,将它进行翻转,第一个数为1,不翻转
结束这个过程后,每一行都应当是以1开头
对于列:
第一列:
其实也就是刚刚经过“移动”后,三行数据的第0位组成的第一列,此时已经都是1,也就是能达到的最大的结果,故不再做改动
第二列:
对这一行进行一个判断,是否“移动”后,1的数量会增加,会增加则移动,不会就进入下一列
第三、四列同理
这里的判断可以这样来写:如果1的数量大于列数除以2(列数奇数就四舍五入进一取整数),那么就对这一列进行移动,否则不变
/**
* @param {number[][]} grid
* @return {number}
*/
var matrixScore = function(grid) {
if (grid.length == 1 && grid[0].length == 1) {
//console.log("1");
return 1;
}
// console.log("原数组:", grid);
let m = grid[0].length; //列 4
let n = grid.length; //行 3
let myarr = grid;
//console.log(m, n);
for (let j = 0; j < n; j++) {
//console.log(myarr[j]);
if (myarr[j][0] == 0) {
for (let i = 0; i < m; i++) {
//console.log("移动");
if (myarr[j][i] == 0) {
myarr[j][i] = 1;
} else {
myarr[j][i] = 0;
}
}
}
//console.log("第一个数为0更改后:", myarr[j]);
}
let count = 0;
//console.log(myarr);
if (myarr[0].length > 1) {
for (let j = 1; j < m; j++) {
for (let i = 0; i < n; i++) {
if (myarr[i][j] == 1) {
count++;
}
}
// console.log(count);
if (count >= Math.ceil(n / 2)) {
//console.log("j=", j, "列不需要改变");
} else {
for (let k = 0; k < n; k++) {
if (myarr[k][j] == 0) {
myarr[k][j] = 1;
} else {
myarr[k][j] = 0;
}
}
}
count = 0;
}
}
// console.log(myarr);
let num = 0;
for (let i = 0; i < n; i++) {
num += parseInt(myarr[i].join(""), 2);
//parseInt("101110100",2)
//console.log("num:", num);
}
//console.log(num);
return num;
};