We have a two dimensional matrix A
where each value is 0
or 1
.html
A move consists of choosing any row or column, and toggling each value in that row or column: changing all 0
s to 1
s, and all 1
s to 0
s.git
After making any number of moves, every row of this matrix is interpreted as a binary number, and the score of the matrix is the sum of these numbers.github
Return the highest possible score.算法
Example 1:数组
Input: [[0,0,1,1],[1,0,1,0],[1,1,0,0]] Output: 39 Explanation: Toggled to [[1,1,1,1],[1,0,0,1],[1,1,1,1]]. 0b1111 + 0b1001 + 0b1111 = 15 + 9 + 15 = 39
Note:this
1 <= A.length <= 20
1 <= A[0].length <= 20
A[i][j]
is 0
or 1
.
这道题给了咱们一个只有0和1的二维数组,说是每一行表明一个数字,咱们能够任意地翻转任意行和列,问如何能使得每一行表明的数字之和最大。在博主看来,这道题仍是挺有意思的,由于你能够写的很复杂,但若是思路巧妙的话,也能够写的很简洁。固然最暴力的解法就是遍历全部的组合,对于一个 mxn 大小的矩阵,每一行均可以选择翻与不翻,同理,每一列也能够选择翻与不翻,那么总共就有 2^(m+n) 种状况,写起来比较复杂。code
这道题最巧妙的解法是用贪婪算法 Greedy Algorithm 来解的,因为数字是由二进制表示的,那么最高位的权重是要大于其余位总和的,好比 1000 就要大于 0111 的,因此当最高位是0的时候,不管如何都是须要翻转当前行的,那么对于 mxn 的数组来讲,每行的二进制数共有n位,最高位是1的话,就是 1<<(n-1),那么共有m行,因此至少能将 m*(1<<(n-1)) 这么大的值收入囊中,既然最高值必定要是1,那么每一行的翻转状况就肯定了,若还想增大数字之和,就只能看各列是否还能翻转了,并且是从次高位列开始看,由于最高位列必须保证都是1。因为每一行的翻转状况已经肯定了,那么如何才能肯定其余位究竟是0仍是1呢,这里就有个 trick,此时就要看它跟最高位是否相同了,若相同的话,无论最高位初始时是0仍是1,最终都要变成1,那么当前位必定最终也会变成1,而一旦跟最高位相反,那么最后必定会是0。咱们翻转当前列的条件确定是但愿翻转以后1的个数要更多一些,这样值才能增长,因此就要统计每列当前的1的个数,若小于0的个数,才进行翻转,而后乘以该列的值,对于第j列,其值为 1<<(n-1-j),参见代码以下:htm
class Solution { public: int matrixScore(vector<vector<int>>& A) { int m = A.size(), n = A[0].size(), res = (1 << (n - 1)) * m; for (int j = 1; j < n; ++j) { int cnt = 0; for (int i = 0; i < m; ++i) { cnt += (A[i][j] == A[i][0]); } res += max(cnt, m - cnt) * (1 << (n - 1 - j)); } return res; } };
Github 同步地址:blog
https://github.com/grandyang/leetcode/issues/861ip
参考资料: