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
參考資料: