Leetcode 782. 变为棋盘 C++

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
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值