942. 增减字符串匹配-简单
题目描述:
由范围 [0,n] 内所有整数组成的 n + 1 个整数的排列序列可以表示为长度为 n 的字符串 s ,其中:
如果 perm[i] < perm[i + 1] ,那么 s[i] == ‘I’
如果 perm[i] > perm[i + 1] ,那么 s[i] == ‘D’
给定一个字符串 s ,重构排列 perm 并返回它。如果有多个有效排列perm,则返回其中 任何一个 。
题解:
实际上只需要按照I和D排序,I升序D降序,遍历s逐个放置元素即可
代码(Go):
func diStringMatch(s string) []int {
i,d := 0,len(s)
re := make([]int,len(s) + 1)
for j,v := range s{
if v == 'I'{
re[j] = i
i++
}else if v == 'D'{
re[j] = d
d--
}
if i == d{
re[j + 1] = i
}
}
return re
}
2451. 差值数组不同的字符串-简单
题目描述:
给你一个字符串数组 words ,每一个字符串长度都相同,令所有字符串的长度都为 n 。
每个字符串 words[i] 可以被转化为一个长度为 n - 1 的 差值整数数组 difference[i] ,其中对于 0 <= j <= n - 2 有 difference[i][j] = words[i][j+1] - words[i][j] 。注意两个字母的差值定义为它们在字母表中 位置 之差,也就是说 ‘a’ 的位置是 0 ,‘b’ 的位置是 1 ,‘z’ 的位置是 25 。
比方说,字符串 “acb” 的差值整数数组是 [2 - 0, 1 - 2] = [2, -1] 。
words 中所有字符串 除了一个字符串以外 ,其他字符串的差值整数数组都相同。你需要找到那个不同的字符串。
请你返回 words中 差值整数数组 不同的字符串。
题解:
这题想起来很简单但是不太好描述,就是如果有哪个差值数组出现了两次及以上那么与它不相等的差值数组一定是那个不同的,我代码写的比较繁琐,用flag判断了很多状态
代码(Go):
func oddString(words []string) string {
dif := make([]int,len(words[0]) - 1)
re1,re2 := 0,0
flag := 1
for d,v := range words{
temp := make([]int,len(v) - 1)
for i := 1;i < len(v);i++{
temp[i - 1] = int(v[i]) - int(v[i - 1])
}
if d == 0{
dif = temp
re1 = d
}else if !compareslice(temp,dif) && flag == 1{
re2 = d
flag = 0
}else if !compareslice(temp,dif) && flag == 0{
return words[re1]
}else if compareslice(temp,dif) && flag == 1{
flag = -1
}else if !compareslice(temp,dif) && flag == -1{
return words[d]
}else if compareslice(temp,dif) && flag == 0{
return words[re2]
}
}
return ""
}
func compareslice(x []int,y []int) bool {
for i,v := range x{
if v != y[i]{
return false
}
}
return true
}
2466. 统计构造好字符串的方案数-中等
题目描述:
给你整数 zero ,one ,low 和 high ,我们从空字符串开始构造一个字符串,每一步执行下面操作中的一种:
将 ‘0’ 在字符串末尾添加 zero 次。
将 ‘1’ 在字符串末尾添加 one 次。
以上操作可以执行任意次。
如果通过以上过程得到一个 长度 在 low 和 high 之间(包含上下边界)的字符串,那么这个字符串我们称为 好 字符串。
请你返回满足以上要求的 不同 好字符串数目。由于答案可能很大,请将结果对 109 + 7 取余 后返回。
题解:
这题本质上就是跳台阶,只不过需要统计的是low到high这一范围而不是最长的值。遍历过程中可以直接加进结果,写的时候没注意,提交之后才想起来不用遍历dp
代码(Go):
func countGoodStrings(low int, high int, zero int, one int) int {
dp := make([]int,high + 1)
dp[0] = 1
for i,_ := range dp{
if i >= zero && i >= one{
dp[i] = (dp[i - zero] + dp[i - one]) % int(math.Pow(10,9) + 7)
}else if i >= zero{
dp[i] = (dp[i - zero]) % int(math.Pow(10,9) + 7)
}else if i >= one{
dp[i] = (dp[i - one]) % int(math.Pow(10,9) + 7)
}
}
re := 0
for i,v := range dp{
if i >= low && i <= high{
re += v
re = re % int(math.Pow(10,9) + 7)
}
}
return re
}
91. 解码方法-中等
题目描述:
一条包含字母 A-Z 的消息通过以下映射进行了 编码 :
‘A’ -> “1”
‘B’ -> “2”
…
‘Z’ -> “26”
要 解码 已编码的消息,所有数字必须基于上述映射的方法,反向映射回字母(可能有多种方法)。例如,“11106” 可以映射为:
“AAJF” ,将消息分组为 (1 1 10 6)
“KJF” ,将消息分组为 (11 10 6)
注意,消息不能分组为 (1 11 06) ,因为 “06” 不能映射为 “F” ,这是由于 “6” 和 “06” 在映射中并不等价。
给你一个只含数字的 非空 字符串 s ,请计算并返回 解码 方法的 总数 。
题目数据保证答案肯定是一个 32 位 的整数。
题解:
常规动态规划,主要就是增加了排除特殊情况
代码(Go):
func numDecodings(s string) int {
dp := make([]int,len(s) + 1)
dp[0] = 1
for i := 1;i <= len(s);i++{
if s[i - 1] != '0'{
dp[i] += dp[i - 1]
}
if i > 1 && s[i - 2] != '0' && ((s[i - 2]- '0') * 10+(s[i - 1] - '0') <= 26){
dp[i] += dp[i - 2]
}
}
return dp[len(s)]
}
总结
动态规划基础篇里的中等题让我做差不多了,明后天可能做一下背包问题,再然后就得去动态规划的大题库里摸奖了