comments | difficulty | edit_url | tags | |||
---|---|---|---|---|---|---|
true |
困难 |
|
给定一个长度为 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.length
1 <= n <= 200
s[i]
不是'I'
就是'D'
我们定义
考虑
如果第 'D'
,那么
如果第 'I'
,那么
最终的答案即为
时间复杂度
class Solution:
def numPermsDISequence(self, s: str) -> int:
mod = 10**9 + 7
n = len(s)
f = [[0] * (n + 1) for _ in range(n + 1)]
f[0][0] = 1
for i, c in enumerate(s, 1):
if c == "D":
for j in range(i + 1):
for k in range(j, i):
f[i][j] = (f[i][j] + f[i - 1][k]) % mod
else:
for j in range(i + 1):
for k in range(j):
f[i][j] = (f[i][j] + f[i - 1][k]) % mod
return sum(f[n][j] for j in range(n + 1)) % mod
class Solution {
public int numPermsDISequence(String s) {
final int mod = (int) 1e9 + 7;
int n = s.length();
int[][] f = new int[n + 1][n + 1];
f[0][0] = 1;
for (int i = 1; i <= n; ++i) {
if (s.charAt(i - 1) == 'D') {
for (int j = 0; j <= i; ++j) {
for (int k = j; k < i; ++k) {
f[i][j] = (f[i][j] + f[i - 1][k]) % mod;
}
}
} else {
for (int j = 0; j <= i; ++j) {
for (int k = 0; k < j; ++k) {
f[i][j] = (f[i][j] + f[i - 1][k]) % mod;
}
}
}
}
int ans = 0;
for (int j = 0; j <= n; ++j) {
ans = (ans + f[n][j]) % mod;
}
return ans;
}
}
class Solution {
public:
int numPermsDISequence(string s) {
const int mod = 1e9 + 7;
int n = s.size();
int f[n + 1][n + 1];
memset(f, 0, sizeof(f));
f[0][0] = 1;
for (int i = 1; i <= n; ++i) {
if (s[i - 1] == 'D') {
for (int j = 0; j <= i; ++j) {
for (int k = j; k < i; ++k) {
f[i][j] = (f[i][j] + f[i - 1][k]) % mod;
}
}
} else {
for (int j = 0; j <= i; ++j) {
for (int k = 0; k < j; ++k) {
f[i][j] = (f[i][j] + f[i - 1][k]) % mod;
}
}
}
}
int ans = 0;
for (int j = 0; j <= n; ++j) {
ans = (ans + f[n][j]) % mod;
}
return ans;
}
};
func numPermsDISequence(s string) (ans int) {
const mod = 1e9 + 7
n := len(s)
f := make([][]int, n+1)
for i := range f {
f[i] = make([]int, n+1)
}
f[0][0] = 1
for i := 1; i <= n; i++ {
if s[i-1] == 'D' {
for j := 0; j <= i; j++ {
for k := j; k < i; k++ {
f[i][j] = (f[i][j] + f[i-1][k]) % mod
}
}
} else {
for j := 0; j <= i; j++ {
for k := 0; k < j; k++ {
f[i][j] = (f[i][j] + f[i-1][k]) % mod
}
}
}
}
for j := 0; j <= n; j++ {
ans = (ans + f[n][j]) % mod
}
return
}
function numPermsDISequence(s: string): number {
const n = s.length;
const f: number[][] = Array(n + 1)
.fill(0)
.map(() => Array(n + 1).fill(0));
f[0][0] = 1;
const mod = 10 ** 9 + 7;
for (let i = 1; i <= n; ++i) {
if (s[i - 1] === 'D') {
for (let j = 0; j <= i; ++j) {
for (let k = j; k < i; ++k) {
f[i][j] = (f[i][j] + f[i - 1][k]) % mod;
}
}
} else {
for (let j = 0; j <= i; ++j) {
for (let k = 0; k < j; ++k) {
f[i][j] = (f[i][j] + f[i - 1][k]) % mod;
}
}
}
}
let ans = 0;
for (let j = 0; j <= n; ++j) {
ans = (ans + f[n][j]) % mod;
}
return ans;
}
我们可以用前缀和优化时间复杂度,使得时间复杂度降低到
class Solution:
def numPermsDISequence(self, s: str) -> int:
mod = 10**9 + 7
n = len(s)
f = [[0] * (n + 1) for _ in range(n + 1)]
f[0][0] = 1
for i, c in enumerate(s, 1):
pre = 0
if c == "D":
for j in range(i, -1, -1):
pre = (pre + f[i - 1][j]) % mod
f[i][j] = pre
else:
for j in range(i + 1):
f[i][j] = pre
pre = (pre + f[i - 1][j]) % mod
return sum(f[n][j] for j in range(n + 1)) % mod
class Solution {
public int numPermsDISequence(String s) {
final int mod = (int) 1e9 + 7;
int n = s.length();
int[][] f = new int[n + 1][n + 1];
f[0][0] = 1;
for (int i = 1; i <= n; ++i) {
int pre = 0;
if (s.charAt(i - 1) == 'D') {
for (int j = i; j >= 0; --j) {
pre = (pre + f[i - 1][j]) % mod;
f[i][j] = pre;
}
} else {
for (int j = 0; j <= i; ++j) {
f[i][j] = pre;
pre = (pre + f[i - 1][j]) % mod;
}
}
}
int ans = 0;
for (int j = 0; j <= n; ++j) {
ans = (ans + f[n][j]) % mod;
}
return ans;
}
}
class Solution {
public:
int numPermsDISequence(string s) {
const int mod = 1e9 + 7;
int n = s.size();
int f[n + 1][n + 1];
memset(f, 0, sizeof(f));
f[0][0] = 1;
for (int i = 1; i <= n; ++i) {
int pre = 0;
if (s[i - 1] == 'D') {
for (int j = i; j >= 0; --j) {
pre = (pre + f[i - 1][j]) % mod;
f[i][j] = pre;
}
} else {
for (int j = 0; j <= i; ++j) {
f[i][j] = pre;
pre = (pre + f[i - 1][j]) % mod;
}
}
}
int ans = 0;
for (int j = 0; j <= n; ++j) {
ans = (ans + f[n][j]) % mod;
}
return ans;
}
};
func numPermsDISequence(s string) (ans int) {
const mod = 1e9 + 7
n := len(s)
f := make([][]int, n+1)
for i := range f {
f[i] = make([]int, n+1)
}
f[0][0] = 1
for i := 1; i <= n; i++ {
pre := 0
if s[i-1] == 'D' {
for j := i; j >= 0; j-- {
pre = (pre + f[i-1][j]) % mod
f[i][j] = pre
}
} else {
for j := 0; j <= i; j++ {
f[i][j] = pre
pre = (pre + f[i-1][j]) % mod
}
}
}
for j := 0; j <= n; j++ {
ans = (ans + f[n][j]) % mod
}
return
}
function numPermsDISequence(s: string): number {
const n = s.length;
const f: number[][] = Array(n + 1)
.fill(0)
.map(() => Array(n + 1).fill(0));
f[0][0] = 1;
const mod = 10 ** 9 + 7;
for (let i = 1; i <= n; ++i) {
let pre = 0;
if (s[i - 1] === 'D') {
for (let j = i; j >= 0; --j) {
pre = (pre + f[i - 1][j]) % mod;
f[i][j] = pre;
}
} else {
for (let j = 0; j <= i; ++j) {
f[i][j] = pre;
pre = (pre + f[i - 1][j]) % mod;
}
}
}
let ans = 0;
for (let j = 0; j <= n; ++j) {
ans = (ans + f[n][j]) % mod;
}
return ans;
}
另外,我们也可以用滚动数组优化空间复杂度,使得空间复杂度降低到
class Solution:
def numPermsDISequence(self, s: str) -> int:
mod = 10**9 + 7
n = len(s)
f = [1] + [0] * n
for i, c in enumerate(s, 1):
pre = 0
g = [0] * (n + 1)
if c == "D":
for j in range(i, -1, -1):
pre = (pre + f[j]) % mod
g[j] = pre
else:
for j in range(i + 1):
g[j] = pre
pre = (pre + f[j]) % mod
f = g
return sum(f) % mod
class Solution {
public int numPermsDISequence(String s) {
final int mod = (int) 1e9 + 7;
int n = s.length();
int[] f = new int[n + 1];
f[0] = 1;
for (int i = 1; i <= n; ++i) {
int pre = 0;
int[] g = new int[n + 1];
if (s.charAt(i - 1) == 'D') {
for (int j = i; j >= 0; --j) {
pre = (pre + f[j]) % mod;
g[j] = pre;
}
} else {
for (int j = 0; j <= i; ++j) {
g[j] = pre;
pre = (pre + f[j]) % mod;
}
}
f = g;
}
int ans = 0;
for (int j = 0; j <= n; ++j) {
ans = (ans + f[j]) % mod;
}
return ans;
}
}
class Solution {
public:
int numPermsDISequence(string s) {
const int mod = 1e9 + 7;
int n = s.size();
vector<int> f(n + 1);
f[0] = 1;
for (int i = 1; i <= n; ++i) {
int pre = 0;
vector<int> g(n + 1);
if (s[i - 1] == 'D') {
for (int j = i; j >= 0; --j) {
pre = (pre + f[j]) % mod;
g[j] = pre;
}
} else {
for (int j = 0; j <= i; ++j) {
g[j] = pre;
pre = (pre + f[j]) % mod;
}
}
f = move(g);
}
int ans = 0;
for (int j = 0; j <= n; ++j) {
ans = (ans + f[j]) % mod;
}
return ans;
}
};
func numPermsDISequence(s string) (ans int) {
const mod = 1e9 + 7
n := len(s)
f := make([]int, n+1)
f[0] = 1
for i := 1; i <= n; i++ {
pre := 0
g := make([]int, n+1)
if s[i-1] == 'D' {
for j := i; j >= 0; j-- {
pre = (pre + f[j]) % mod
g[j] = pre
}
} else {
for j := 0; j <= i; j++ {
g[j] = pre
pre = (pre + f[j]) % mod
}
}
f = g
}
for j := 0; j <= n; j++ {
ans = (ans + f[j]) % mod
}
return
}
function numPermsDISequence(s: string): number {
const n = s.length;
let f: number[] = Array(n + 1).fill(0);
f[0] = 1;
const mod = 10 ** 9 + 7;
for (let i = 1; i <= n; ++i) {
let pre = 0;
const g: number[] = Array(n + 1).fill(0);
if (s[i - 1] === 'D') {
for (let j = i; j >= 0; --j) {
pre = (pre + f[j]) % mod;
g[j] = pre;
}
} else {
for (let j = 0; j <= i; ++j) {
g[j] = pre;
pre = (pre + f[j]) % mod;
}
}
f = g;
}
let ans = 0;
for (let j = 0; j <= n; ++j) {
ans = (ans + f[j]) % mod;
}
return ans;
}