Leetcode 782. 变为棋盘
题目
一个 N x N的 board 仅由 0 和 1 组成 。每次移动,你能任意交换两列或是两行的位置。
输出将这个矩阵变为 “棋盘” 所需的最小移动次数。“棋盘” 是指任意一格的上下左右四个方向的值均与本身不同的矩阵。如果不存在可行的变换,输出 -1。
示例:
输入: board = [[0,1,1,0],[0,1,1,0],[1,0,0,1],[1,0,0,1]]
输出: 2
解释:
一种可行的变换方式如下,从左到右:
0110 1010 1010
0110 --> 1010 --> 0101
1001 0101 1010
1001 0101 0101
第一次移动交换了第一列和第二列。
第二次移动交换了第二行和第三行。
输入: board = [[0, 1], [1, 0]]
输出: 0
解释:
注意左上角的格值为0时也是合法的棋盘,如:
01
10
也是合法的棋盘.
输入: board = [[1, 0], [1, 0]]
输出: -1
解释:
任意的变换都不能使这个输入变为合法的棋盘。
提示:
- board 是方阵,且行列数的范围是[2, 30]。
- board[i][j] 将只包含 0或 1。
题解
我们无论怎么改变行和列,一行或一列中其1、0的数量都是不变的,因此,我们需要保证每行或每列表示的状态只有2种,也就是我们以第一行为基准,其余行要么和其相同,要么和它相反。
保证这个条件后,我们先调整行,最终行的状态要么01010101或者10101010,显然,和基准行的差别应该得在偶数个,差别/2别是移动数。调整列与调整行一致。
详细过程见代码
代码
bool isSame(vector<int>& one,vector<int>& two){ //两个状态相同
int n = one.size();
for(int i=0; i<n; i++)
if(one[i] != two[i]) return false;
return true;
}
bool isReverse(vector<int>&one,vector<int>& two){ //两个状态相反
int n = one.size();
for(int i=0; i<n; i++)
if(one[i]+two[i] != 1) return false;
return true;
}
bool isFinish(vector<int>& one){ //判断一行或一列中1、0能否隔开,也就是要么出现次数相同,要么有一个会多1个
int n = one.size(),cnt=0;
for(int i=0; i<n; i++)
if(one[i]==1) cnt++;
if(n%2 == 0){
if(cnt == n/2) return true;
return false;
}else if(cnt == n/2 || cnt==n/2+1) return true;
return false;
}
int getStep(vector<int>& one){ //获取移动步
int n = one.size(),different = -1;
// 01010101
int choice = 0,now=0;
for(int i=0; i<n; i++){
if(one[i] != choice) now++;
choice = (choice+1)%2;
}
if(now%2 == 0) different = now/2;
// 10101010
choice = 1; now=0;
for(int i=0; i<n; i++){
if(one[i] != choice) now++;
choice = (choice+1)%2;
}
if(now%2 == 0){
if(different == -1) different = now/2;
else different = min(different,now/2);
}
return different;
}
int movesToChessboard(vector<vector<int>>& board) {
int n = board.size();
if(n==0 || n==1) return 0;
vector<int> colum;
colum.push_back(board[0][0]);
for(int i=1; i<n; i++){
colum.push_back(board[i][0]);
if(isSame(board[0],board[i]) || isReverse(board[0],board[i])) continue;
return -1;
}
if(!isFinish(board[0]) || !isFinish(colum)) return -1;
int rowStep = getStep(board[0]);
if(rowStep == -1) return -1;
int columnStep = getStep(colum);
if(columnStep == -1) return -1;
return rowStep+columnStep;
}
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/transform-to-chessboard
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。