首页 > 其他分享 >【Leetcode 每日一题】782. 变为棋盘

【Leetcode 每日一题】782. 变为棋盘

时间:2024-12-08 10:29:42浏览次数:5  
标签:782 int 异或 ++ length board diff 棋盘 Leetcode

问题背景

一个 n × n n \times n n×n 的二维网络 b o a r d board board 仅由 0 0 0 和 1 1 1 组成 。每次移动,你能交换任意两列或是两行的位置。
返回 将这个矩阵变为 “棋盘” 所需的最小移动次数 。如果不存在可行的变换,输出 − 1 -1 −1。
“棋盘” 是指任意一格的上下左右四个方向的值均与本身不同的矩阵。

数据约束

  • n = b o a r d . l e n g t h n = board.length n=board.length
  • n = b o a r d [ i ] . l e n g t h n = board[i].length n=board[i].length
  • 2 ≤ n ≤ 30 2 \le n \le 30 2≤n≤30
  • b o a r d [ i ] [ j ] board[i][j] board[i][j] 将只包含 0 0 0 或 1 1 1

解题过程

首先要确定所给矩阵能否转化成题目要求的形式。从结果上来看,符合条件的矩阵只由两种行构成,它们都是 0 0 0 和 1 1 1 交替出现,区别在于首位数字是 0 0 0 还是 1 1 1。交替出现,意味着同一行中 0 0 0 和 1 1 1 的数量之差不能超过 1 1 1,否则无法实现转化。
同样的道理,按列来看,矩阵同样需要满足这样的特征。
但是不必要按行并且按列来遍历矩阵,可以将第一行作为标准,之后每一行都应该与标准完全相同或者完全相反,否则就要返回 − 1 -1 −1。
交换次数的计算,依赖的是纯粹的数学规律。参考 灵神的分析,若用 d i f f diff diff来表示当前行与标准行之间不同的位数:

  • 若 n n n为奇数,那么交换的次数是 d i f f 2 \frac {diff} {2} 2diff​。
  • 若 n n n为偶数,那么交换的次数是 m i n ( d i f f , n − d i f f ) 2 \frac {min(diff, n - diff)} {2} 2min(diff,n−diff)​。

根据标准行的首位是 0 0 0 还是 1 1 1,可以用是否需要异或运算来对 d i f f diff diff 进行计数,而不必要实际地构造标准行来进行判断:

  • 若标准行的首位为 0 0 0,遍历的过程中可以用 ( i % 2 ) ⊕ 0 (i \% 2) \oplus 0 (i%2)⊕0 来累计。
  • 若标准行的首位为 1 1 1,遍历的过程中可以用 ( i % 2 ) ⊕ 1 (i \% 2) \oplus 1 (i%2)⊕1 来累计。

综合上述情况,考虑到 0 0 0 异或任何数都等于该数本身,可以用一个标志位 b i t bit bit 来表示是否需要异或 1 1 1。

根据当前数字是 0 0 0 还是 1 1 1,使用长度为 2 2 2 的哈希表来方便地统计元素的数量,也是一种常用的重要技巧。另外还需要注意积累的是,利用异或的定义直接来统计 d i f f diff diff 这样的操作。

具体实现

class Solution {
    public int movesToChessboard(int[][] board) {
        int n = board.length;
        int[] firstRow = board[0];
        int[] firstCol = new int[n];
        int[] rowCount =  new int[2];
        int[] colCount =  new int[2];
        // 统计第一行和第一列中 0 和 1 的数量
        for(int i = 0; i < n; i++) {
            rowCount[firstRow[i]]++;
            firstCol[i] = board[i][0];
            colCount[firstCol[i]]++;
        }
        // 如果第一行或者第一列的 0 与 1 数量之差超过 1,那么无法实现转换
        if(Math.abs(rowCount[0] - rowCount[1]) > 1 || Math.abs(colCount[0] - colCount[1]) > 1) {
            return -1;
        }
        // 判断剩余行是否和第一行完全相同或者完全相反
        for(int[] row : board) {
            // 将其中第一位数字作为标准,后面所有位上的情况应该与之相同
            boolean same = row[0] == firstRow[0];
            for(int i = 0; i < n; i++) {
                if((row[i] == firstRow[i]) != same) {
                    return -1;
                }
            }
        }
        return min(firstRow, rowCount) + min(firstCol, colCount);
    }

    private int min(int[] arr, int[] count) {
        int n = arr.length;
        int bit = count[1] > count[0] ? 1 : 0;
        int diff = 0;
        for(int i = 0; i < n; i++) {
            // 利用异或的定义,直接统计 diff
            diff += (i % 2) ^ arr[i] ^ bit;
        }
        return n % 2 == 0 ? Math.min(diff, n - diff) >>> 1 : diff >>> 1;
    }
}

标签:782,int,异或,++,length,board,diff,棋盘,Leetcode
From: https://blog.csdn.net/2401_88859777/article/details/144322281

相关文章

  • [LeetCode] 2684. Maximum Number of Moves in a Grid
    Youaregivena0-indexedmxnmatrixgridconsistingofpositiveintegers.Youcanstartatanycellinthefirstcolumnofthematrix,andtraversethegridinthefollowingway:Fromacell(row,col),youcanmovetoanyofthecells:(row-1,col+......
  • Leetcode Hot100 | Day02 双指针
    4.移动零283.移动零给定一个数组nums,编写一个函数将所有0移动到数组的末尾,同时保持非零元素的相对顺序。请注意,必须在不复制数组的情况下原地对数组进行操作。示例1:输入:nums=[0,1,0,3,12]输出:[1,3,12,0,0]示例2:输入:nums=[0]输出:[0]题解:......
  • 详解LeetCode地下城游戏(动态规划)——区分两种状态表示形式
    地下城游戏题目链接:174.地下城游戏状态表示:按照以往题的表示,dp[i][j]表示:从起点(0,0)位置到达(i,j)位置时,所需的最小初始健康值。但是如果这么去表示,不仅要考虑到达(i,j)位置的最小初始健康值,由于魔法球的存在,还需要考虑到达(i,j)位置时的健康值,因为魔法球会对算后续位置的最小初始......
  • leetcode3351 好子序列的元素之和
    给定数组num[n],如果一个子序列中任意两个相邻元素的绝对差恰好为1,则称它为好子序列,返回nums中所有好子序列的元素之和,结果对1E9+7取模。注意,长度为1的子序列算好子序列。1<=n<=1E5;0<=nums[i]<=1E5分析:设f[x]表示以x结尾的所有子序列元素之和,g[x]表示以x结尾的子序列个数,从左到......
  • leetcode 1208. 尽可能使字符串相等
    1208.尽可能使字符串相等其中,字符串s和t只包含小写字母法一:使用额外空间classSolution{public:intequalSubstring(strings,stringt,intmaxCost){intsize=s.size();vector<int>cost(size);for(inti=0;i<size;i++)c......
  • leetcode 1493. 删掉一个元素以后全为 1 的最长子数组
    1493.删掉一个元素以后全为1的最长子数组法一:递推classSolution{public://在删掉元素的结果数组中,最长的且只包含1的非空子数组存在两种情况://1.这个子数组在原数组中本身就是连续的,无论删或者不删其他的元素,它都是最长的且只包含1的非空子数组;//2.这个子数组原......
  • 【每日一题】 688. 骑士在棋盘上的概率
    在一个 nxn 的国际象棋棋盘上,一个骑士从单元格 (row,column) 开始,并尝试进行 k 次移动。行和列是 从0开始 的,所以左上单元格是 (0,0) ,右下单元格是 (n-1,n-1) 。象棋骑士有8种可能的走法,如下图所示。每次移动在基本方向上是两个单元格,然后在正交方......
  • 【Leetcode Top 100】146. LRU 缓存
    问题背景请你设计并实现一个满足LRU(最近最少使用)缓存约束的数据结构。实现LRUCache类:LRUCache(intcapacity)以正整数作为容量cap......
  • 【Leetcode 每日一题】688. 骑士在棋盘上的概率
    问题背景在一个n×nn\timesnn×n的国际象棋棋盘上,一个骑士从单元格......
  • LeetCode 263[丑数]
    题目链接LeetCode263[丑数]详情实例提示题解思考题目对丑数的定义:只包含质因数2、3、5的正整数条件一:只包含质因数2、3、5条件二:正整数 对于条件二很好筛选:如果给定值n小于1,即给定值为0或者是负数,此时条件二不满足,则返回false该部分的代码实现如下:......