https://leetcode.com/problems/transform-to-chessboard/description/
题目大意:一个N*N的01序列,问最少通过交换行列多少次能使得0周围都是1,1周围都是0.
解题思路:
1.我的思路比较蠢
一开始的时候有很多坑,不过也是过了,思路大致思想就是贪心,从行入手比较相邻的两列,若相同则,往后找到一个不同的交换整个列,(但是此时有一个坑 ,例如这样 10100,可以发现如果按照我贪心的交换 会判断这种情况是错误的)为了应对这种情况,如果当此时判断的是最后一列,且前面的列没有进行过交换,则将最后一列交换到最开始。这样交换完成后,最后判断N*N的矩阵能否满足要求。
下面就要开始思考怎样计算最少的交换次数,这里有个坑,得考虑 N的奇偶,因为如果是偶数个N,可以使0开头也可以是1,这样会影响到交换次数。
2.优秀的解题思路
- 考虑最终满足条件的情况,要么是010101... 要么是10101...这样的序列,也就是最终就两种情况,行的不同情况也就只有两种。当交换两列的时候,不会影响最终行的数目(即不管怎样交换列,行不同的情况就只有两种)
- 可以确定当N为偶数时,01在每行里数量相同,N为奇数时,为N/2和N/2+1
以上可以确定是否能满足情况。
通过直接比较行和列与最终满足的情况不同位置的个数,就可以得到最少的交换次数。因为只要能组成满足题意的序列,则交换行列不会影响行和列不同序列的个数,所以调整一行或者一列满足01交错的序列,其他序列也能满足。
class Solution {
public int movesToChessboard(int[][] board) {
int n = board.length;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if((board[0][0]^board[0][j]^board[i][0]^board[i][j])==1)
return -1;
}
}
int row=0,col=0;
int cntrow=0,cntcol=0;
for(int i=0;i<n;i++)
{
row+=board[0][i];
col+=board[i][0];
if(board[0][i]!=i%2) cntrow++; //01010...
if(board[i][0]!=i%2) cntcol++; //01010...
}
//System.out.println(row+" "+col);
if(row<n/2 || row>(n+1)/2) return -1;
if(col<n/2 || col>(n+1)/2) return -1;
int res=0;
if(n%2==0)
{
res+=Math.min(cntrow,n-cntrow);
res+=Math.min(cntcol,n-cntcol);
}
else
{
if(cntrow%2==1)
cntrow = n-cntrow;
if(cntcol%2==1)
cntcol = n-cntcol;
res=cntrow+cntcol;
}
return res/2;
}
}
我的代码有点长
class Solution {
public int movesToChessboard(int[][] board) {
int n = board.length;
int cnt = 0;
//看列
int tmp;
int pre;
for(int i=0;i<n;i++)
{
int[] a = new int[n];
for(int j=0;j<n;j++)
a[j] = board[i][j];
// for(int j=0;j<n;j++) System.out.print(a[j]);
// System.out.println();
for(int j=1;j<n;j++)
{
if(board[i][j] == board[i][j-1]) {
int flag = 0;
for (int k = j + 1; k < n; k++) {
if (board[i][k] != board[i][j]) {
flag = 1;
for (int l = 0; l < n; l++) {
tmp = board[l][j];
board[l][j] = board[l][k];
board[l][k] = tmp;
}
}
if (flag == 1) break;
}
if (flag == 0) {
if (j == n - 1 && board[i][j] != board[i][0]) {
for (int x = 0; x < n - 1; x++) {
for (int y = 0; y < n; y++) {
tmp = board[y][j];
board[y][j] = board[y][x];
board[y][x] = tmp;
}
}
} else
return -1;
}
}
}
int tmpcnt=0;
for(int j=0;j<n;j++)
{
// System.out.println(a[j]+" "+board[i][j]);
if(a[j]!=board[i][j]) tmpcnt++;
}
if(n%2==0)
{
int tmpcnt2=0;
for(int j=0;j<n;j++)
{
// System.out.println(a[j]+" "+board[i][j]);
if(a[j]!= ( (board[i][j]+1)%2) ) tmpcnt2++;
}
cnt+=Math.min(tmpcnt/2,tmpcnt2/2);
}
else
cnt+= tmpcnt/2 ;
}
//System.out.println(cnt);
//行
for(int i=0;i<n;i++)
{
int[] a = new int[n];
for(int j=0;j<n;j++)
a[j] = board[j][i];
// for(int j=0;j<n;j++) System.out.print(a[j]);
// System.out.println();
for(int j=1;j<n;j++)
{
if(board[j][i] == board[j-1][i])
{
int flag=0;
for(int k=j+1;k<n;k++)
{
if(board[k][i]!=board[j][i])
{
flag=1;
for(int l=0;l<n;l++)
{
tmp = board[j][l];
board[j][l] = board[k][l];
board[k][l] = tmp;
}
}
if(flag==1) break;
}
if(flag==0)
{
if(j==n-1 && board[j][i]!=board[0][i])
{
for(int x=0;x<n-1;x++)
{
for(int y=0;y<n;y++)
{
tmp = board[j][y];
board[j][y] = board[x][y];
board[x][y] = tmp;
}
}
}
else
return -1;
}
}
}
int tmpcnt=0;
for(int j=0;j<n;j++)
{
if(a[j]!=board[j][i]) tmpcnt++;
}
if(n%2==0)
{
int tmpcnt2=0;
for(int j=0;j<n;j++)
{
// System.out.println(a[j]+" "+board[i][j]);
if(a[j]!= ( (board[j][i]+1)%2) ) tmpcnt2++;
}
cnt+=Math.min(tmpcnt/2,tmpcnt2/2);
}
else
cnt+= tmpcnt/2 ;
}
//check if ready
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
//System.out.print(board[i][j]);
if(i!=0 && board[i][j]==board[i-1][j]) return -1;
if(j!=0 && board[i][j]==board[i][j-1]) return -1;
}
//System.out.println();
}
return cnt;
}
}
782
.
Transform to Chessboard