码迷,mamicode.com
首页 > 其他好文 > 详细

782. Transform to Chessboard

时间:2020-05-09 17:12:03      阅读:55      评论:0      收藏:0      [点我收藏+]

标签:sum   public   and   情况   else   transform   from   column   接下来   

问题:

给定一个由0,1组成的N*N的数组,问是否能进行多次行交换,列交换,使得数组成为一个国际象棋盘(01交叉排列)

可以则返回交换次数,否则返回-1

Examples:
Input: board = [[0,1,1,0],[0,1,1,0],[1,0,0,1],[1,0,0,1]]
Output: 2
Explanation:
One potential sequence of moves is shown below, from left to right:

0110     1010     1010
0110 --> 1010 --> 0101
1001     0101     1010
1001     0101     0101

The first move swaps the first and second column.
The second move swaps the second and third row.


Input: board = [[0, 1], [1, 0]]
Output: 0
Explanation:
Also note that the board with 0 in the top left corner,
01
10

is also a valid chessboard.

Input: board = [[1, 0], [1, 0]]
Output: -1
Explanation:
No matter what sequence of moves you make, you cannot end with a valid chessboard.
Note:

board will have the same number of rows and columns, a number in the range [2, 30].
board[i][j] will be only 0s or 1s.

  

解法:

先考虑能满足条件的数组都有什么特征:

1.若某一行(列)为:101001101,那么该数组的其他行(列)只能为以下两种情况:

   101001101:与给定内容一致

   010110010:将给定内容各位取补

那么,在这条规律下,对于数组的某一个元素 board[i][j] 与其偏移基准横坐标[0][j],纵坐标[i][0],原点[0][0]组成的矩形

四点值只可能有三种情况:四个0,四个1,两个1两个0。

那么则有,若 board[i][j]^board[i][0]^board[0][j]^board[0][0]==1 ,那么就违反上述情况,不满足条件所要求的数组,则需返回-1

 

2.某一行(列)中 1 和 0 需各占一半。

由于特征 1 已经固定了每个点的特性,则只需要将第一行和第一列的01数量特性限制,即可使得全节点满足特性 2

那么遍历 i:0~n,计算1的数量 SumCol 和 SumRow

若所得结果,SumCol !=n/2 同时 !=(n+1)/2 )不满足 1 和 0 各占一半的话,返回-1

SumRow 同上。

 

??特别的,在计算SumCol和SumRow的同时,可计算如果需要进行交换,那么需要交换几次。

需要交换:不满足1和0相隔出现,即index为奇数时出现 0,index为偶数时出现 1;或者 index为奇数时出现 1,index为偶数时出现 0

SwapCol+=board[0][i]==i%2;

若满足1和0相隔出现,上述公式可得,SwapCol==0或者n

有一个违反位,SwapCol==1或者n-1
有两个违反位,SwapCol==2或者n-2

……

SwapRow同理可得。

??注意,这里交换的次数x和n-x,交换出来的效果都是一样的。

我们最后需要得到的结果是交换动作的次数,一次交换,可以换掉两行(列),

因此,我们要的结果应为(SwapCol+SwapRow)/2

 

接下来,考虑Swap的取值选择上:

由于一次交换会换掉两行或两列,

那么我们所取的SwapCol和SwapRow应为2的倍数,即为偶数。同时根据题意,要求最少次数

那么有:

当n为奇数时,Swap为奇数的话,则取剩下的一半 n-Swap

当n为偶数是,取 min(Swap, n-Swap)

 

代码参考:

 1 class Solution {
 2 public:
 3     int movesToChessboard(vector<vector<int>>& board) {
 4         int n=board.size(), SumCol=0, SumRow=0, SwapCol=0, SwapRow=0;
 5         for(int i=0; i<n; i++){
 6             for(int j=0; j<n; j++){
 7                 if(board[i][j]^board[i][0]^board[0][j]^board[0][0]==1) return -1;
 8             }
 9         }
10         for(int i=0; i<n; i++){
11             SumCol+=board[0][i];
12             SumRow+=board[i][0];
13             SwapCol+=board[0][i]==i%2;//=010...?N ->=01[1]...:N-1 ->=0[01]...:N-2
14             SwapRow+=board[i][0]==i%2;//=010...?N:0
15             //对于一行中交换 SwapCol 次,也就相当于交换余下的 n-SwapCol 次,效果一样
16         }
17         if(SumCol!=n/2 && SumCol!=(n+1)/2) return -1;
18         if(SumRow!=n/2 && SumRow!=(n+1)/2) return -1;
19         if(n%2){//奇数个,由于没交换一次,其实Swap数是2,那么只选择Swap数为2的倍数
20             if(SwapCol%2) SwapCol=n-SwapCol;//偶数SwapCol=奇数n-奇数SwapCol
21             if(SwapRow%2) SwapRow=n-SwapRow;//偶数SwapRow=奇数n-奇数SwapRow
22         }else{//偶数个,则选择交换次数少的:偶数SwapCol=偶数n-偶数SwapCol
23             SwapCol=min(SwapCol,n-SwapCol);
24             SwapRow=min(SwapRow,n-SwapRow);
25         }
26         return (SwapCol+SwapRow)/2;
27     }
28 };

 

782. Transform to Chessboard

标签:sum   public   and   情况   else   transform   from   column   接下来   

原文地址:https://www.cnblogs.com/habibah-chang/p/12858395.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!