LeetCode之黑白方格画

LeetCode LCP22.黑白方格画

为了达成我的算法工程师之梦,我最近在刷LeetCode上面的题目,奈何本人实在有点太菜鸡了,所以在csdn下记录一些思考历程和解题过程,希望与大家共同进步。会尽力及时更新,另外各位有有意思的题目,也欢迎与我交流。

黑白方格画之题目描述:


链接附在这里:https://leetcode.cn/problems/ccw6C7 大家可以自行前去解一番

黑白方格画之解题思路:

乍一看这题目挺好理解的,只要注意几个关键的条件

1、要做到整行以及整列进行填涂,且所选个数可为0—意思是有两种涂法:要么只涂行或者列,要么可以行和列交叉来涂
2、画板不能转动—意思是行和列的涂法并不重合,例如涂1行和涂一列记为两种不同方案

几个特殊填法

考虑到k值的不同,有那么几种特殊情况咱们得单列出来:
1、0<k<n的情况,只要涂了,一下笔那必须是整行或者整列,至少有n个格子黑化,所以k不可能小于n,于是返回值为0
2、k=0的情况,选择什么都不做,这时候画板还是那个干净的画板,这种填涂方案返回值为1
然后就是一般情况n<=k<=n*n的情况

思考历程

本菜鸡一开始把焦点放在了k值上,想要通过划分k的情况,使用条件语句进行判断,进而求取方案数量,我是这么想的,,,,,
几种特殊填法的返回值毋庸置疑,接下来我们来考虑一般情况下的k值。第一种:它是n的倍数,这样就只能选择整行涂或者整列涂,而不能交叉涂(但是被输入值(4,12)给否定了,这个东西告诉我其实整除也可以交叉涂)。第二种:它不是n的倍数。这种情况下k值是固定的那几个里面才可以,例如n是3的时候,k若不整除,可以为4,但是不能是5。基于这种想法我写出了这么个玩意儿:
反面教材

事实证明,咳咳~只有一些测试用例可以通过,但是不是全部的用例。当我再去找未通过的测试用例分析它没通过的原因时,发现这种思路太笨拙了,不能列举出全部的情况。

正解是什么

本菜鸡前天思考了两个小时,思考出上面的垃圾,很是苦恼,然后一看题目难度:简单。enmmmmm更苦恼了~于是昨天思考一天人生。没错,思考人生。
今天再去看这道题目,想想这种题的正解是什么,是规律,是一般规律,我们必须找到适合一般情况的一般规律,才可以拿到正解,否则永远无法穷举出来。
但是这个规律是什么,其实一开始拿到题目的时候就有这个规律的雏形。就是被重叠的格子数。当行列交叉填涂时,一定会有部分格子被重叠,那这部分就不能全部计入数量中。这不是小学的问题吗?嗯 确实简单。
示例图
看到这个图了吗,蓝色和绿色是我们选择的行和列,交叉之后重叠的格子为橙黄色。有什么规律?
橙黄色的数量是选择的行数乘以选择的列数。
bingo!
但是就算是找到了这个规律我依然没有想出要怎么写代码。于是,我看了一个同学的题解是这样的。题解
给大家附上链接:https://leetcode.cn/problems/ccw6C7/solution/shu-xue-yi-ge-xun-huan-ji-ke-by-o240qnhz-g8x2/
短短几行~简单且粗暴

上代码

于是我把焦点放在了选择的行数和列数上,假设行为i,列为j,涂的时候重叠的数量就是ij个格子,于是最终黑化的格子数量为ni+jn-ij,也就是我们的k。接着就是循环i,j,如果k与黑化的格子数量相等,那么就有可选涂的方案,否则不存在这种k,即方案个数为0.接下来就是排列组合的知识,把不同的方案加起来就是最终的方案。代码如下:

import math
class Solution:
    def paintingPlan(self, n: int, k: int) -> int:
        #题目分析:如果k是n的整数倍,那么在选择是只能选择某些行或者某些列,而不能交叉选择,因为行和列交叉选择必至少有一个格子重复
        if k<n and k!=0:
            return 0
        elif k==0 or k==n**2:
            return 1
        else:
            res=0
            m=int(k/n)
            for i in range(0,n):
                for j in range(0,n):
                    if k==n*(i+j)-i*j:
                        res+=int(math.factorial(n)**2/math.factorial(i)/math.factorial(n-i)/math.factorial(j)/math.factorial(n-j))
                    else:
                        res+=0
            return res

其中factorial()是求阶乘的函数,factorial(n)=n!。最后就是这样啦~

通过

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值