Leetcode 903. Valid Permutations for DI Sequence DI序列的个数

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)

------------------------------------------------------------------------------------------------------

DP is intuition, but how to provide the right DP recursive formula is the difficulty. Let dp[i][j] stands for the count of valid sequence {0,1,2,...,i} ending with j, i.e., there's not a valid sequence {0,1,2,...,i} ending with i+1, i+2...l-1. Specifically, 

1. When i-1, dp[i-1][0] stands for the count of valid sequence {0,1,2,...,i-1} ending with 0

2. When i, dp[i][0] stands for the count of valid sequence {0,1,2,...,i} ending with 0

Therefore,

  1. If (S[i-1], S[i]) is increasing, dp[i][0]=sum(dp[i-1][<0])
  2. If (S[i-1], S[i]) is decreasing, sequences from dp[i-1][1], dp[i-1][2],...,dp[i-1][i-1] could all append 0 in the ending. However, how could we ensure sequences from dp[i-1][1], dp[i-1][2],...,dp[i-1][i-1] don't contains 0? It will generate duplicate sequences. This is the key point for this problem. We could pick items (>=0) out of sequences from dp[i-1][1], dp[i-1][2],...,dp[i-1][i-1]. The range of these items is [0,i-1]. If we add 1 for all these items to generate new sequences, the range of picked out items will be [1,i]. Since counts of old sequences and new sequences are exactly same, we could append 0 to new sequences. So dp[i-1][1], dp[i-1][2],...,dp[i-1][i-1] are parts of dp[i][0]
  3. If (S[i-1], S[i]) is decreasing, dp[i-1][0] is also part of dp[i][0] as the description 2. So dp[i][0]=sum(dp[i-1][>=0])

Finally, we could sumarize the recursive formula as :

  1. If (S[i-1], S[i]) is increasing, dp[i][j]=sum(dp[i-1][
  2. If (S[i-1], S[i]) is decreasing, dp[i][j]=sum(dp[i-1][>=j])

Take care the slices for matrix in python 

So the code is :

class Solution:
    def numPermsDISequence(self, S):
        mod = 1000000007
        l = len(S) + 1
        dp = [[0 for j in range(l)] for i in range(l)]
        dp[0][0] = 1
        for i in range(1, l):
            for j in range(i+1):
                if (S[i - 1] == 'I'):
                    dp[i][j] = sum(dp[i-1][0:j])%mod
                else:
                    dp[i][j] = sum(dp[i-1][j:])%mod
        return sum(dp[l-1][:])%mod

s = Solution()
print(s.numPermsDISequence("DID"))

 

你可能感兴趣的:(算法,leetcode)