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,所以遍历整个矩阵首列,如果该位为0,就把该行翻转(翻转操作对1异或即可)。

接下来处理首列之外的数据,因为第一列已经为1,所以不能进行行翻转了,就遍历之后的列,如果0多就进行翻转。

处理完数据之后,矩阵就变成了我们想要的矩阵,从第一列开始,把整列加起来,然后依次乘2加列和,最后得到的结果就是我们要的值,

	class Solution {
		//要想值最大,第一列必须都为1,所以先遍历每一行,把首位为0的翻转
		//然后从第二列开始,如果是0多久翻转,1多就不变
	    public int matrixScore(int[][] A) {
	    	int res = 0;
            //对首位为0的行进行翻转
	    	for(int i = 0; i < A.length; i++) {
	    		if(A[i][0] == 0) {
	    			reverse(A[i]);
	    		}
	    	}
            //处理第一列之后的数据,按列来处理
	    	for(int j = 1; j < A[0].length; j++) {
	    		int num = 0;
	    		for(int i = 0; i < A.length; i++) {
	    			if(A[i][j] == 0) {
	    				num++;
	    			}
	    			if(num > A.length/2) {
	    				for(int k = 0; k < A.length; k++) {
	    					A[k][j] ^= 1;
	    				}
	    				break;
	    			}
	    		}
	    	}
            //计算结果
	    	for(int j = 0; j < A[0].length; j++) {
	    		res = res << 1;
	    		for(int i = 0; i < A.length; i++) {
	    			res += A[i][j];
	    		}
	    	}
	    	return res;
	    }
        public void reverse(int[] arr) {
	    	for(int i = 0; i < arr.length; i++) {
	    		arr[i] ^= 1;
	    	}
	    }
    }

但是这样处理并不是最优解,因为我们要想想我们要的结果是什么,只是一个最大值。但是在求这个最大值的过程中我们对矩阵做了很多没必要的操作,于是对解法进行优化。

第一步还是不变,对首位为0的行进行翻转。

重点在第二步和求和的过程中,我们开始做的是如果0的个数大于列长度的一半,就翻转,这个操作的目的是把列中大多数变成1,最后相加。但是仔细一想,最后都是1相加,这个1的个数就是一列中0和1数量的较大值,所以我们没有必要对0进行翻转,只是计算数量即可,并且在计算数量的过程中就可以求出返回值。

	class Solution {
		//看到的新解法
		//首先把第一列全部变成1,res加上行数(因为第一列全部为1)
		//然后再遍历之后的每一列,0和1比较大的那个数量就是我们要的(省去了翻转的过程)
		//res * 2 再加上这个数量,遍历完就是我们要的结果
	    public int matrixScore(int[][] A) {
	    	int res = 0;
	    	res += A.length;
	    	for(int i = 0; i < A.length; i++) {
	    		if(A[i][0] == 0) {
	    			for(int j = 0; j < A[0].length; j++) {
	    				A[i][j] ^= 1;
	    			}
	    		}
	    	}
	    	for(int j = 1; j < A[0].length; j++) {
	    		int num = 0;
	    		for(int i = 0; i < A.length; i++) {
	    			if(A[i][j] == 1) {
	    				num++;
	    			}
	    		}
	    		num = Math.max(num, A.length-num);
	    		res = (res << 1) + num;
	    	}
	    	return res;
	    }
    }
posted @ 2020-03-26 23:20  风语如歌j  阅读(197)  评论(0编辑  收藏  举报