编程题中常常遇到动态规划问题,这里做一个记录与分类。
非常见
-
不冲突字符串的最小删除次数。
Composition: 给定一个字符串,规定M个不能相邻的字母对,问最少删除多少个字母,可以得到一个合法的字符串。
5 # 字符串长度 abcde # 字符串 3 # 不能相邻的对的个数(M),注意,如果ab是不能相邻的对,那么表示ab, ba都是不合法的。 ac # pair 1 ab # pair 2 de # pair 3
我们将问题转化一下,将其变为“求合法字符串的最大长度l”,然后用总长度L减去l就是删除的字母个数。有了这个转化,我们设置一个状态数组
dp[26]
, 表示的是以字母dp[i]
结尾的合法字符串的最大长度,其中i表示字母a, b, c, d, …, z,共26个取值. 设字符串为str
.初始条件设置,
dp[i] = 0, if str[0] != i
, 否则dp[i] = 1
.我们从位置1到结束处理
str
, 对位置k
, 该位置的字母为c = str[k]
, 根据给定的不合法列表,我们可以得出字母c
合法的前一个字母集合legal_char_set
, 因此dp[c] = max( dp[l] + 1 ) for every l in legal_char_set
. 最后,dp
数组中最大值就是合法字符串最大长度l,由此也得到了删除个数。当然我们也可以用二阶的DP,即
dp[i][j]
表示处理到位置i
时以字母j
结尾的合法字符串的最大长度。更新上,对于当前位置k
的字母c
, 更新dp[k][c]
与上面相同,更新其余dp[k][others]
则简单赋值为dp[k-1][others]
即可? 其实二阶真的是完全是没有必要的。微软笔试题目,没有做出来… 请教了下师弟,知道了做法。