Leetcode 782. 变为棋盘
本文最后更新于217 天前,其中的信息可能已经过时,如有错误请发送邮件到2446865563@qq.com

1.题目基本信息

1.1.题目描述

一个 n x n 的二维网络 board 仅由 0 和 1 组成 。每次移动,你能交换任意两列或是两行的位置。

返回 将这个矩阵变为 “棋盘” 所需的最小移动次数 。如果不存在可行的变换,输出 -1。

“棋盘” 是指任意一格的上下左右四个方向的值均与本身不同的矩阵。

1.2.题目地址

https://leetcode.cn/problems/transform-to-chessboard/description/

2.解题方法

2.1.解题思路

逆向推理。

从目标状态向初始状态进行转换。经过几次模拟可以看出,逆向移动得到的网格的共同性质:每行或每列的0和1的个数差绝对值不会超过1;移动之后,每行和第一行要么完全相同,完全完全相反,列同理。第2个性质和第1个性质分别在形和数上保证能够移动成功

2.2.解题步骤

第一步,根据第1个性质和第2个性质排除不能转移到"棋盘"状态的情况

  • 1.1.第1行统计与判断

  • 1.2.第一列统计与判断

  • 1.3.判断行列的非同即反性(如果行非同即反,则列也可以保证)

第二步,计算最少交换次数。仔细观察可以看出每行或者每列的交换具有等价性,所以可以通过第一行和第一列的最小交换次数计算总最小交换次数。列的交换对行的最小交换次数不会有影响(完全不同的两行,分别转为为0xxx和1xxx的最小转次数是相等的)。定义diff为行列与目标行列元素不同的位置的个数,如果行列数为偶数,最小转移次数为(diff,n-diff)//2;如果行列数为奇数,例如每行中1的个数比0的个数多1,则为转换为1010...1状态的最小转换次数,算diff//2

第三步,最终的结果为calcMinSwapCnt(firstRow)+calcMinSwapCnt(firstCol)

3.解题代码

python代码

class Solution:
    def movesToChessboard(self, board: List[List[int]]) -> int:
        # 思路:逆向推理。从目标状态向初始状态进行转换。经过几次模拟可以看出,逆向移动得到的网格的共同性质:每行或每列的0和1的个数差绝对值不会超过1;移动之后,每行和第一行要么完全相同,完全完全相反,列同理。第2个性质和第1个性质分别在形和数上保证能够移动成功
        # 参考:灵神-https://leetcode.cn/problems/transform-to-chessboard/solutions/2997293/tu-jie-ni-xiang-si-wei-pythonjavaccgojsr-mixb/?envType=problem-list-v2&envId=3yidzXie
        n = len(board)
        # 第一步,根据第1个性质和第2个性质排除不能转移到"棋盘"状态的情况
        # 1.1.第1行统计与判断
        firstRow = board[0]
        cnt1 = [0] * 2
        for v in firstRow:
            cnt1[v] += 1
        if abs(cnt1[1] - cnt1[0]) > 1:
            return -1
        # 1.2.第一列统计与判断
        firstCol = [board[i][0] for i in range(n)]
        cnt2 = [0] * 2
        for v in firstCol:
            cnt2[v] += 1
        if abs(cnt2[1] - cnt2[0]) > 1:
            return -1
        # 1.3.判断行列的非同即反性(如果行非同即反,则列也可以保证)
        for row in board[1:]:
            same = row[0] == firstRow[0]
            for x, y in zip(row, firstRow):
                if (x == y) != same:
                    return -1
        # 第二步,计算最少交换次数。仔细观察可以看出每行或者每列的交换具有等价性,所以可以通过第一行和第一列的最小交换次数计算总最小交换次数。列的交换对行的最小交换次数不会有影响(完全不同的两行,分别转为为0xxx和1xxx的最小转次数是相等的)。定义diff为行列与目标行列元素不同的位置的个数,如果行列数为偶数,最小转移次数为(diff,n-diff)//2;如果行列数为奇数,例如每行中1的个数比0的个数多1,则为转换为1010...1状态的最小转换次数,算diff//2
        def calcMinSwapCnt(arr):
            cnts = [0] * 2
            for num in arr:
                cnts[num] += 1
            if cnts[0] == cnts[1]:
                diff = sum(arr[i] != i % 2 for i in range(n))
                return min(diff, n - diff) // 2
            else:
                if cnts[0] > cnts[1]:
                    diff = sum(arr[i] != i % 2 for i in range(n))
                else:
                    diff = sum(arr[i] == i % 2 for i in range(n))
                return diff // 2
        # 第三步,最终的结果为calcMinSwapCnt(firstRow)+calcMinSwapCnt(firstCol)
        return calcMinSwapCnt(firstRow) + calcMinSwapCnt(firstCol)

4.执行结果

觉得有帮助可以投喂下博主哦~感谢!

作者:geek007

转载请注明文章地址及作者哦~
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇