/*
从左往右的尝试模型1
规定1和A对应,2和B对应,3和C对应...
那么一个数字字符串比如“111”就可以转化为"AAA","KA","AK"
给定一个只有数字字符组成的字符串str,返回有多少种转化结果
11111
1 1111
11 111
111 不能转换
此题可以改成动态规划的解法
*/
func TestNumber(t *testing.T) {
fmt.Println(number("11111"))
fmt.Println(numberforDp("11111"))
}
func number(str string) int {
if str == "" || len(str) == 0 {
return 0
}
return processNumber(str,0)
}
// str[0...i-1]上已经转化完了,固定了
// i 之前的位置,如何转化已经做过的决定了,不用再关心
// i... 有多少种转化的结果
func processNumber(str string,i int) int {
if i == len(str) { //base case
return 1 //没有字符的时候,可以转化为“” or 找到一种答案时,返回一种答案
}
if str[i] == '0' { //i 没有到终止位置, 0无法被转化
return 0
}
if str[i] == '1' { // str[i]字符不是’0‘
res := processNumber(str,i+1) // i自己作为单独的部分,后序有多少种方法
if i + 1 < len(str) {
res += processNumber(str, i + 2) //(i和i+1) 作为单独的部分,后序有多少种
}
return res
}
if str[i] == '2' {
res := processNumber(str,i+1) // i自己作为单独的部分,后序有多少种方法
if i + 1 < len(str) && str[i+1] >='0' && str[i+1] <= '6' { // i 和 i+1 作为单独的部分并且没有超过 26,后序有多少种方法
res += processNumber(str, i + 2) //(i和i+1) 作为单独的部分,后序有多少种
}
return res
}
// str[i] == '3' ~ '9'
return processNumber(str,i+1) //只有去i+1 位置 1种选择
}
/*
任何一个位置依赖 i + 1,或 i + 2 的值,所以这张表从右往左填写
*/
func numberforDp(str string ) int {
//第一步
//if str == "" || len(str) == 0 {
// return 0
//}
if str == "" || len(str) == 0 {
return 0
}
N := len(str)
dp := make([]int,N+1)
//dp怎么生成
//第二步,i在 = N 的时候 dp[N] = 1
// if i == len(str) { //base case
// return 1 //没有字符的时候,可以转化为“” or 找到一种答案时,返回一种答案
// }
dp[N] = 1
for i := N -1; i >= 0; i-- {
//dp[i] = ?
/*
if str[i] == '0' { //i 没有到终止位置, 0无法被转化
return 0
}
if str[i] == '1' { // str[i]字符不是’0‘
res := processNumber(str,i+1) // i自己作为单独的部分,后序有多少种方法
if i + 1 < len(str) {
res += processNumber(str, i + 2) //(i和i+1) 作为单独的部分,后序有多少种
}
return res
}
if str[i] == '2' {
res := processNumber(str,i+1) // i自己作为单独的部分,后序有多少种方法
if i + 1 < len(str) && str[i+1] >='0' && str[i+1] <= '6' { // i 和 i+1 作为单独的部分并且没有超过 26,后序有多少种方法
res += processNumber(str, i + 2) //(i和i+1) 作为单独的部分,后序有多少种
}
return res
}
*/
//所有return 都是设置dp[i]的时刻
if str[i] == '0' { //i 没有到终止位置, 0无法被转化
dp[i] = 0
}
if str[i] == '1' { // str[i]字符不是’0‘
dp[i] = dp[i+1] // i自己作为单独的部分,后序有多少种方法
if i + 1 < len(str) {
dp[i] += dp[i + 2] //(i和i+1) 作为单独的部分,后序有多少种
}
}
if str[i] == '2' {
dp[i] = dp[i+1] // i自己作为单独的部分,后序有多少种方法
if i + 1 < len(str) && str[i+1] >='0' && str[i+1] <= '6' { // i 和 i+1 作为单独的部分并且没有超过 26,后序有多少种方法
dp[i] += dp[i + 2] //(i和i+1) 作为单独的部分,后序有多少种
}
}
}
//最后一步,暴力递归需要0状态,所以返回dp[0]
//return processNumber(str,0)
return dp[0]
}
动态规划——从左往右的尝试模型1
最新推荐文章于 2024-07-22 15:00:08 发布