动态规划——Valid Permutations for DI Sequence
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) 这道题目出自LeetCode,可以采用动态规划方法来解决 这篇博客主要是对LeetCode给出的第一种时间复杂度为O(n^3)的动态规划解法进行解释,题目的大意不再具体解释,有点英文基础的查查百度也能知道
这个题说的是个什么意思。由于采用的是动态规划解法,所以要找出状态和状态转移方程。LeetCode给的那个解法里面把状态dp[i][j]确定为以下的含义:
我们每次只注重最后一个数字在整个数组序列中 小->大 排列后的位置,如果给数组编号为i = 0、1、...、n,我们关注的焦点dp[i][j]可以解释为长度为i+1的数组中某个方案中
其最后一个数字即第i个数字在这i+1个数字中处于第j+1小位置的方案的数量,比如dp[0][0]的意义就是长度为长度为1的数组{0}按字符串S的要求下重新排列后的新数组其第0个数字在整个数组中排最小的方案数字,而且易知dp[0][0]=1。
而且dp[0]只用dp[0][0]这一个元素,其他的用不上,对于每个i = 0、1、...、n,我们只用dp[i][0..i]这些元素。
状态转移方程的解释更加复杂,如果S[i-1]=='D',递减,则p[i]<p[i-1],这个时候dp[i][j]是所有dp[i-1][j<=k<=i-1]的和,k之所以小于i是因为对于dp[i-1]来说它一共就i个成员,下标访问到i会越界,k大等于j的原因不好解释,
有一个替换的问题在里面,因为dp[i]比dp[i-1]多一个元素,它们所代表的数组也是前者比后者多一个,由于dp[i]所属的数组方案中按 小->大的数组和dp[i-1]的那个数组中第k(1<=k<=i)个数字是一样的,这里我不知道怎么叙述好,
反正就是dp[i]所代表的那个长的最后一位可以使用dp[i-1]所代表的那个短的最后一位,因为是递减,可以把dp[i]代表的数组中多出来的那一个最大的数组顶在倒数第二个位置上;如果S[i-1]=='T',由于dp[i]所属的数组方案中按 小->大
的数组和dp[i-1]的那个数组中第k(1<=k<=i)个数字是一样的,dp[i][j]是所有dp[i-1][0<=k<j]的和。这个题的思路上确实是比较复杂的,也不是很好叙述清楚它的思路。这个题最后一个注意点就是要求模,记住每次求模即可。 下面直接上代码:
int numPermsDISequence(string S){
int MOD = ;
int n = S.length();
int**dp = new int*[n + ];
for (int i = ; i <= n; i++)
dp[i] = new int[n + ];
for (int i = ; i <= n;i++)
for (int j = ; j <= n; j++){
if (i == )dp[i][j] = ;
else dp[i][j] = ;
}
for (int i = ; i <= n; i++){
for (int j = ; j <= i; j++){
if (S[i - ] == 'D'){
for (int k = j; k < i; k++){
dp[i][j] += dp[i - ][k];
dp[i][j] %= MOD;
}
}
else{
for (int k = ; k < j; k++){
dp[i][j] += dp[i - ][k];
dp[i][j] %= MOD;
}
}
}
}
for (int i = ; i <= n; i++){
for (int j = ; j <= n; j++)
cout << dp[i][j] << " ";
cout << endl;
}
int ans = ;
for (int i = ; i <= n; i++){
ans += dp[n][i];
ans %= MOD;
}
for (int i = ; i <= n; i++)
delete[]dp[i];
delete[]dp;
return ans;
}
动态规划——Valid Permutations for DI Sequence的更多相关文章
- [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 &q ...
- [Swift]LeetCode903. DI 序列的有效排列 | Valid Permutations for DI Sequence
We are given S, a length n string of characters from the set {'D', 'I'}. (These letters stand for &q ...
- 903. Valid Permutations for DI Sequence
We are given S, a length n string of characters from the set {'D', 'I'}. (These letters stand for &q ...
- leetcode903 Valid Permutations for DI Sequence
思路: dp[i][j]表示到第i + 1个位置为止,并且以剩下的所有数字中第j + 1小的数字为结尾所有的合法序列数. 实现: class Solution { public: int numPer ...
- [Algo] 66. All Valid Permutations Of Parentheses I
Given N pairs of parentheses “()”, return a list with all the valid permutations. Assumptions N > ...
- Swift LeetCode 目录 | Catalog
请点击页面左上角 -> Fork me on Github 或直接访问本项目Github地址:LeetCode Solution by Swift 说明:题目中含有$符号则为付费题目. 如 ...
- All LeetCode Questions List 题目汇总
All LeetCode Questions List(Part of Answers, still updating) 题目汇总及部分答案(持续更新中) Leetcode problems clas ...
- leetcode hard
# Title Solution Acceptance Difficulty Frequency 4 Median of Two Sorted Arrays 27.2% Hard ...
- 【LeetCode】分治法 divide and conquer (共17题)
链接:https://leetcode.com/tag/divide-and-conquer/ [4]Median of Two Sorted Arrays [23]Merge k Sorted Li ...
随机推荐
- Redis protocol (redis通信协议)
以前只会用redis -cli客户端, 或者在java程序里使用jedis来作为介质与redis服务器通信.这两天正好在实习中接触了一点这方面的内容. 五一放假就稍微翻了翻redis相关资料. 本篇博 ...
- 用 Mathematica 获取图片的 RGB 三基色
ColorConvert[*, "RGB"] // InputForm 其中 * 表示你把你的图片拖入 Mathematica 中.
- 给一个Unix域套接字bind一个路径名
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <strings.h& ...
- for 循环 与forEach 里面return 的区别
for 循环里面 return 可以直接终止 跳出 循环 forEach 是中断本次循环 直接 下一个循环 forEach想要取到值之后 直接跳出循环 可以用 try catch let arr = ...
- Error:Execution failed for task ':app:transformResourcesWithMergeJavaResForDebug'
Information:Gradle tasks [:app:assembleDebug]Error:Execution failed for task ':app:transformResource ...
- SQL Server - Partition by 和 Group by对比
参考:https://www.cnblogs.com/hello-yz/p/9962356.html —————————————————— 今天大概弄懂了partition by和group by的区 ...
- 简单使用Markdown
Markdown是一种纯文本格式的标记语言.通过简单的标记语法,它可以使普通文本内容具有一定的格式. 相比WYSIWYG编辑器 优点: 1.因为是纯文本,所以只要支持Markdown的地方都能获得一样 ...
- Java消息队列--ActiveMq 初体验
1.下载安装ActiveMQ ActiveMQ官网下载地址:http://activemq.apache.org/download.html ActiveMQ 提供了Windows 和Linux.Un ...
- English 动词篇
动词后加to do 和 doing的记忆口诀 一.只能用动名词(ing)作宾语 [口诀] 考虑建议盼原谅,承认推迟没得想. 避免错过继续练,否定完成停欣赏. 禁止想象才冒险,不禁介意弃逃亡. cons ...
- linux 批量测试域名返回码脚本
需求:应用要求覆盖host并测试 1.创建一个host.txt的文件来存放需要修改的host记录 2.过滤出host.txt域名列并新生成一个curl.txt文件 cat host.txt |awk ...