1. 程式人生 > 其它 >LeetCode 861 翻轉矩陣後的得分

LeetCode 861 翻轉矩陣後的得分

技術標籤:Leetcodejava

有一個二維矩陣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。為了做到這一點,我們可以翻轉那些最左邊的數不為1的那些行,而其他的行則保持不動。

當將每一行的最左邊的數都變為 1 之後,就只能進行列翻轉了。為了使得總得分最大,我們要讓每個列中 1的數目儘可能多。因此,我們掃描除了最左邊的列以外的每一列,如果該列 0 的數目多於 1 的數目,就翻轉該列,其他的列則保持不變。

對於最左邊的列而言,由於最優情況下,它們的取值都為1,因此每個元素對分數的貢獻都為2^{n-1},總貢獻是m*2^{n-1}

對於第j 列(j>0,此處規定最左邊的列是第0列)而言,我們統計這一列0,1 的數量,令其中的最大值為k,則k是列翻轉後的1的數量,該列的總貢獻為k*2^{n-j-1}需要注意的是,在統計0,1 的數量的時候,要考慮最初進行的行反轉

注意本題只用返回分數,可以不對矩陣進行操作變換。

public static int matrixScore(int[][] A) {
    	int m = A.length, n = A[0].length;
    	int score = m * (1 << (n-1));
    	
    	for (int j = 1; j < n; j++) {
			int one_nums = 0;
			for (int i = 0; i < m; i++) {
				if(A[i][0] == 1) {
					one_nums += A[i][j];
				}
				else if (A[i][0] == 0) {	 // 如果這一行進行了行反轉,則該元素的實際取值為 1 - A[i][j]
					one_nums += 1 - A[i][j];
				}
			}
			int k = Math.max(one_nums, m-one_nums);
			score += k * (1 << (n-j-1));
		}
		return score;
    }