本质是求i个空格,j个取值范围能够有多少递增的组合。
dp[i][j] 表示i个空格,j个取值范围可以有多少递增的组合
假设0到i-1的所有组合数量已知,求第i个空格,第i个空格有j个选择,
每个选择对应一个dp[i-1],把dp[i-1][0]~dp[i-1][j]加起来就是i个空格的所有组合dp[i][j]。
0 1 2 3 4 5
0 1 3 6 10 15
0 1 4 10 20 35
dp[i][j] 表示i个空格,j个取值范围可以有多少递增的组合
假设0到i-1的所有组合数量已知,求第i个空格,第i个空格有j个选择,
每个选择对应一个dp[i-1],把dp[i-1][0]~dp[i-1][j]加起来就是i个空格的所有组合dp[i][j]。
0 1 2 3 4 5
0 1 3 6 10 15
0 1 4 10 20 35
0 1 5 15 35 70
import java.util.*; public class Solution { public int FillArray (int[] a, int k) { long ans = 1; int n = a.length; //横坐标是数组的长度,纵坐标是最大的值 long[][] dp = new long[n+1][k+1]; for(int i = 1; i <= n; i++){ for(int j = 1; j <= k; j++){ if(i == 1){ //只有一个空格的话,最大为j,那么一定有j中填充方法 dp[i][j] = j; }else{ //dp[i][j-1]实际上就对应这dp[i-1][0]~dp[i-1][j-1]的和 dp[i][j] = (dp[i-1][j] + dp[i][j-1]) % 1000000007; } } } //例子 a:2 0 0 4 5 k:6 for(int i = 0; i < a.length;i++){ if(a[i] == 0){ //终于遇见了一个0(空格) int p = i;//标记一下这一段第一个出现的空格 p = 1 //统计一下这一段出现了多少的空格 while(i < a.length && a[i] == 0) i++;//出现了2个 //此时i为3 //down和up决定了这2个空格的取值范围 int down = (p == 0) ? 1 : a[p-1]; //如果p为0说明数组的第一个元素就是0,取值下限就是1, //如果p非0,下限就是本轮中第一次出现0的前一个元素的值即a[p-1](2) int up = (i == a.length) ? k : a[i]; //如果本段中的i为a数组的长度,上限就是题目规定的k的大小 //如果不是,上限就是此时a[i](4) int opportunity = up - down + 1; //总的取值范围为4-2+1 = 3 可以取2 3 4 这三个值 int len = i - p; //0的个数是i-p(3-1=2) ans = (ans * dp[len][opportunity]) % 1000000007; //每段算出来的结果是需要相乘的 //此时的i下标为3的地方(其值必不为0,回到循环后直接++跳过) } } //返回的值也一定要进行取模操作 return (int)(ans % 1000000007); } }