一个 n x n 的二维网络 board 仅由 0 和 1 组成 。每次移动,你能任意交换两列或是两行的位置
返回将这个矩阵变为 “棋盘” 所需的最小移动次数 ,如果不存在可行的变换,输出 -1
1. 数学方法
移动使满足条件的题目,首先得判断棋盘是否满足条件
容易从棋盘得知,需要满足以下几个条件
- 棋盘只存在两种行(列),即矩阵秩为2
- 对应的两种行(列)每个元素相异,即两行(列)正交
- 对于任意一行(列),0和1的个数差不超过1
判断思路:将所有行和列与第一行、第一列比较,判断是否满足相同或相异
计算判断第一行和第一列0和1的个数差值即可(满足条件的话,其它相同或相异的也必然满足)
移动次数计算:假定一种顺序,计算不在位的个数,分奇偶进行处理即可
class Solution {
public:
int movesToChessboard(vector<vector<int>>& board) {
int n = board.size(), rowSum = 0, colSum = 0, rowDiff = 0, colDiff = 0;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j)
//对于任意行和列,要么和第一行(第一列)全同,要么全异
if (board[0][0] ^ board[i][0] ^ board[0][j] ^ board[i][j]) return -1;
}
//判断行和列不在位的个数,同时求和用于判断是否符合要求(0和1个数相差不超过一)
for (int i = 0; i < n; ++i) {//先假设正确顺序为(101010....)
rowSum += board[0][i];
colSum += board[i][0];
rowDiff += (board[i][0] == i % 2);
colDiff += (board[0][i] == i % 2);
}
//如果第一行1的个数少于一半或多于一半(奇偶)
if (n / 2 > rowSum || rowSum > (n + 1) / 2) return -1;
//如果第一列1的个数少于一半或多于一半(奇偶)
if (n / 2 > colSum || colSum > (n + 1) / 2) return -1;
if (n % 2) {//如果为奇数(01010->10101无法进行转化,只能转化为01010)
if (rowDiff % 2) rowDiff = n - rowDiff;//不在位为奇数,转化为偶数
if (colDiff % 2) colDiff = n - colDiff;//不在位为奇数,转化为偶数
} else {//如果为偶数
rowDiff = min(n - rowDiff, rowDiff);//计算第一行最小不在位
colDiff = min(n - colDiff, colDiff);//计算第一列最小不在位
}
return (rowDiff + colDiff) / 2;//移动一次可以解决两个不在位
}
};
标签:rowDiff,int,个数,变为,board,第一列,棋盘,colDiff,LeetCode
From: https://www.cnblogs.com/929code/p/16614878.html