We are given S
, a length n
string of characters from the set {'D', 'I'}
. (These letters stand for "decreasing" and "increasing".)
A valid permutation is a permutation P[0], P[1], ..., P[n]
of integers {0, 1, ..., n}
, such that for all i
:
- If
S[i] == 'D'
, thenP[i] > P[i+1]
, and; - If
S[i] == 'I'
, thenP[i] < P[i+1]
.
How many valid permutations are there? Since the answer may be large, return your answer modulo 10^9 + 7
.
Example 1:
Input: "DID"
Output: 5
Explanation:
The 5 valid permutations of (0, 1, 2, 3) are:
(1, 0, 3, 2)
(2, 0, 3, 1)
(2, 1, 3, 0)
(3, 0, 2, 1)
(3, 1, 2, 0)
Note:
1 <= S.length <= 200
S
consists only of characters from the set{'D', 'I'}
.
思路:
猜到了有O(N^3)的DP解法,
注意到了用1-3填和用2-4填的个数是一样
但还是没有想到状态转移方程(也就是DP数组的含义)
为了能进行状态转移,定义dp[i][j]表示:使用1-i这些数字的情况下,以j结尾的合理数组个数,计算dp[i][j]的过程如下:
1. 如果s[i-2]=='D',说明第i-1位的数要比j大,第i-1位的数据范围是[j+1,i],j在第i位上,所以就把大于等于j的数都往左shift一位(这样2者是等价的,满足A一定满足B,满足B一定满足A),这样前i-1位就又是连续的[1,i-1],就可以继续用DP数组的含义。具体到代码就是,k的范围是range(j,i),而不是range(j+1,i)
2. 如果s[i-2]=='I',数字i不在前i-1位,不用shift
class Solution(object):
def numPermsDISequence(self, s):
"""
:type S: str
:rtype: int
"""
mod=10**9+7
n=len(s)+1
dp=[[0 for _ in range(n+1)] for _ in range(n+1)]
dp[1][1]=1
for i in range(2,n+1):
for j in range(1, i+1):
if s[i-2]=='D':
for k in range(j,i): # here start from j, regard as swap value j with i, then shift all values no larger than j
dp[i][j]+=dp[i-1][k]
dp[i][j]%=mod
else:
for k in range(1,j):
dp[i][j]+=dp[i-1][k]
dp[i][j]%=mod
# print(dp)
return sum(dp[n])%mod
s=Solution()
print(s.numPermsDISequence("DID"))