903. DI 序列的有效排列
题目描述
给定一个长度为 n 的字符串 s ,其中 s[i] 是:
“D”意味着减少,或者“I”意味着增加
有效排列 是对有 n + 1 个在 [0, n] 范围内的整数的一个排列 perm ,使得对所有的 i:
- 如果
s[i] == 'D',那么perm[i] > perm[i+1],以及; - 如果
s[i] == 'I',那么perm[i] < perm[i+1]。
返回 有效排列 perm的数量 。因为答案可能很大,所以请返回你的答案对 109 + 7 取余。
示例 1:
输入:s = "DID" 输出:5 解释: (0, 1, 2, 3) 的五个有效排列是: (1, 0, 3, 2) (2, 0, 3, 1) (2, 1, 3, 0) (3, 0, 2, 1) (3, 1, 2, 0)
示例 2:
输入: s = "D" 输出: 1
提示:
n == s.length1 <= n <= 200s[i]不是'I'就是'D'
解法
方法一:动态规划
思考
长度为 \(n\) 的 DI 串对应 \(0..n\) 的排列,\(n\) 可达 \(200\),枚举排列不可行。关键在于相对名次:放完前 \(i\) 个数后,下一个数在剩余数中的名次 \(j\) 决定与上一位置的升降关系。
定义 \(f[i][j]\) 为前 \(i\) 个字符、以名次 \(j\) 结尾的方案数。遇 'D' 时从更大的名次转移,遇 'I' 时从更小的名次转移;已用名次压缩到 \([0,i]\),得到立方级递推。
我们定义 \(f[i][j]\) 表示字符串的前 \(i\) 个字符中,以数字 \(j\) 结尾的满足题目要求的排列的数量。初始时 \(f[0][0]=1\),其余 \(f[0][j]=0\)。答案为 \(\sum_{j=0}^n f[n][j]\)。
考虑 \(f[i][j]\),其中 \(j \in [0, i]\)。
如果第 \(i\) 个字符 \(s[i-1]\) 是 'D',那么 \(f[i][j]\) 可以从 \(f[i-1][k]\) 转移而来,其中 \(k \in [j+1, i]\),而由于 \(k-1\) 最大只能为 \(i-1\),我们将 \(k\) 向左移动一位,那么 \(k \in [j, i-1]\),因此有 \(f[i][j] = \sum_{k=j}^{i-1} f[i-1][k]\)。
如果第 \(i\) 个字符 \(s[i-1]\) 是 'I',那么 \(f[i][j]\) 可以从 \(f[i-1][k]\) 转移而来,其中 \(k \in [0, j-1]\),因此有 \(f[i][j] = \sum_{k=0}^{j-1} f[i-1][k]\)。
最终的答案即为 \(\sum_{j=0}^n f[n][j]\)。
时间复杂度 \(O(n^3)\),空间复杂度 \(O(n^2)\)。其中 \(n\) 是字符串的长度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | |
方法二:前缀和优化
思考
方法一每次转移要扫一段 \(k\),同一行上相邻的 \(j\) 共享几乎相同的区间和。用按方向滚动的前缀和在常数时间内得到 \(\sum f[i-1][k]\),时间降为平方级,状态定义不变。
我们可以用前缀和优化状态转移,将时间复杂度降低到 \(O(n^2)\)。空间复杂度仍为 \(O(n^2)\)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | |
方法三:滚动数组优化
思考
\(f[i]\) 只依赖 \(f[i-1]\),二维表中多数空间可以丢掉。用一维数组滚动,按 'D'/'I' 的方向维护累加和写入新一层,空间降至线性。
在方法二的基础上,我们使用滚动数组将空间复杂度优化到 \(O(n)\)。时间复杂度仍为 \(O(n^2)\)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | |