问题:LCP 22. 黑白方格画
分析
分析:LeetCode给的是简单题,但是我觉得把这个题从题面转化成组合数问题还是需要一定时间的——需要画图。首先需要明确:我们只能一次画一整行或者一整列。带着这个限制我们往下看。
思想就是组合,为什么是组合可以看一下解答里面带图的分析,相信你一看就懂。
注意几点:
- 边界条件,k=1和k=0的情况
- 其次就是返回的条件:
- 当前选取的
i
行格子已经超过了总格子数k
,那么直接返回之前累积的数; - 当前选取的
i
行格子刚好了总格子数k
,那么返回之前累积的数+combination(i,n) * 2
,为什么是乘2呢?因为我们是按行选的,因为棋盘是方形的,所以旋转过来也是可以的,即2倍的组合数; - 只有剩下所需要涂的格子数是剩余的一行的格子数的整数倍才能涂完,这一条件通过
j * (n - i) == k- i * n
实现。
- 当前选取的
Code:
class Solution {
public int paintingPlan(int n, int k) {
if (k == 0) return 1;
if (k == 1)
if (n == 1) return 1; else return 0;
int count = 0;
// i表示一次涂了多少行
for (int i = 1; i < n; i++) {
// 剩余的格子数
int resBlocks = k - i * n;
if (resBlocks < 0) return count;
if (resBlocks == 0) return count+combination(i,n) * 2;
int j = resBlocks / (n - i);
if (j == n) return count+1;
if (j * (n - i) == k- i * n && j < n && j > 0) count += (combination(i,n) * combination(j, n));
}
return count;
}
// 求组合数
public int combination(int i, int j) {
int res1 = 1;
int res2 = 1;
for(int k = 0; k < i; k++ ) {
res1 *= (j-k);
res2 *= k+1;
}
return res1 / res2;
}
}