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