903. Valid Permutations for DI Sequence

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zjucor/article/details/82557070

We are given S, a length n string of characters from the set {'D', 'I'}. (These letters stand for "decreasing" and "increasing".)

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', then P[i] > P[i+1], and;
  • If S[i] == 'I', then P[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. 1 <= S.length <= 200
  2. 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一位,这样前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"))
                    

猜你喜欢

转载自blog.csdn.net/zjucor/article/details/82557070
DI