动态规划之三—— 从暴力递归到动态规划_数字字符串转字母字符串

题目:

规定1 和A 对应,2 和B对应,3 和C 对应 ... 那么一个数字字符串,比如"111" 就可以转化为:"AAA" 、"KA"、"AK" 。要求:给定一个只有数字字符组成的字符串str, 返回有多少种转化结果?

题目分析:

根据题目描述可知:数字1~26 是有对应的字母与之对应的,但超过26的数字无法给出对应字母,表明给出的是一个无效字符。对于数字0,比较特殊,当它单独出现的时候,没有与之对应的字母,但是它的前面是1 或者2 时,合并组成的两位数10 和20 是有可以转化成对应字母的,当然大于2后(30 >26)又为无效。

思路:

1.逐一遍历字符串, 当遍历到最后一个字符时,即完成一次转化。

2.当strindex == '0' 时, 即表明出现无效字符。因为'0' 不可单独出现,一定是作为两位数中的个位数参与判断。

  1. 当strindex != '0' 时判断下一个字符

  2. 当strindex+1 没有越界,并且strindex 与 strindex+1 组成的两位数没有超过26, 则两这两个字符合并后,继续判断strindex+2;

  3. 步骤1 和步骤2 即为递归的base case

代码实现:

cpp 复制代码
//代码段1
#include <iostream>
#include <string>

using namespace std;

int process(string& str, int index){
    if(index == str.lenght()){
        return 1;
    }
    if(str[index] == '0'){
        return 0;
    }

    int way = process(str, index+1);
    if(index+1 < str.length() && (str[index]-'0')*10 - str[index+1]-'0' < 27){
        way += process(str, index+2);
    } 
    return way;
}
int number(string& str){
    if(str.length() == 0)
    {
        return 0;
    }
    return process(str, 0);
}
int main(){

    string str = "112";
    cout << "number: " << number(str) << endl;
    return 0;
}

运行结果:

优化为动态规划:

将递归过程改写为动态规划表来实现。

思路:

  1. 分析递归函数的可变参数,发现只有index一个, 所以动态规划表是1维的,即动态规划表只与index有关。

  2. 因为递归的base case中,迫使递归结束原因是 index == 字符数组长度值N,且表示完成1次转化,所以动态规划表dpArr 的大小为N+1, 且dpArrN = 1;

  3. 通过已知的dpArrN ,从N到0, 依次填写动态规划表,即将调用递归函数的地方改为调用动态规划表dpArr

  4. 动态规划函数返回的是dpApp0;

代码实现:

cpp 复制代码
#include <string>
#include <iostream>

using namespace std;

int dp(string& str){
    if(str.length() == 0) return 0;
    int N = str.length();
    int dpArr[N+1] = {0};
    
    dpArr[N] = 1;
    for(int i = N-1; i >= 0; i--){
        if(str[i] != '0'){
            int way = dpArr[i+1];
            if(i+1 < N && (str[i] - '0')*10 - str[i+1]-'0' >27){
                way += dpArr[i+2];
            }
            dpArr[i] = way;
        }
    }     
    return dpArr[0];
}

int main(){
    string str = "112"
    cout << "dp: " << dp(str) << endl;
    return 0;
}

运行结果:

相关推荐
Navigator_Z3 小时前
LeetCode //C - 1317. Convert Integer to the Sum of Two No-Zero Integers
c语言·算法·leetcode
D e re k ZH4 小时前
C++ 标准库算法全景指南
数据结构·c++·算法
冻柠檬飞冰走茶5 小时前
字母移动游戏题解:贪心求最长可保留连续子串(附 C 实现)
c语言·开发语言·数据结构·算法·动态规划
雪落漂泊5 小时前
C++算法 二分查找篇(上)
开发语言·c++·算法
LabVIEW开发7 小时前
LabVIEW 连接板:28 个端子怎么排,优先级怎么定
java·算法·labview
严肃小白兔8 小时前
MATLAB 数值计算中的精度与误差问题:浮点运算、误差传播与数值稳定性
人工智能·算法·matlab
青少儿编程课堂9 小时前
蓝桥杯青少组图形化省考报名倒计时·全国青少年信息素养大赛·电子学会图形化考级:校园黑白棋人机对战解析
c++·python·算法·bfs·信息学竞赛
jktantan10 小时前
注解式脱敏:用 Jackson 的 ContextualSerializer 做字段级策略(一)
spring boot·后端·算法·spring cloud·系统架构
Dream it possible!1 天前
LeetCode 面试经典 150_多维动态规划_交错字符串(97_C++_中等)
算法·leetcode·面试·动态规划