DFS求解DecodeWays输出所有情况和方法数

该博客介绍了一道LeetCode上的问题,探讨如何使用DFS(深度优先搜索)来找出字符串的所有解码方法及其数量。在解码过程中,考虑到字符'0'不能单独作为有效解码,博主通过动态规划和DFS算法展示了如何找到所有可能的解码序列。示例代码展示了如何进行DFS搜索,并给出了输出解码序列的结果。
摘要由CSDN通过智能技术生成

这是一道leetcode上的原题,在笔试面试中也经常遇到。一般我们只要求出所有的解码种类数目就可,并没有要求输出所有的解码序列,这里运用DFS解决了这个问题。题目描述如下:
这里写图片描述
现在我们先求解一下编码方法数。通过题目我们可以知道,编码是通过一个或两个字符来实现,对于一个编码“12125”;可以一个一个字符的进行编码,也可以两个来进行,这就类似于我们的爬楼梯问题,一次可以上一个台阶,一次也可以上两个台阶,求所有的方式,何其相似。因此我们也可以运用动态规划来求解本题,只是要加上一些条件判断。一个字符是如果是‘0’,那么不能解码,就依赖于他前一个字符看看能否组成10-26之间的数进行解码,因此对于从0-n位置的字符,他的方法数为f(n)=f(n-1)+f(n-2);即对n位置,他可以选择自己单独解码,也可选择与前面一起解码。具体代码如下:

int numDecodings(string &s)
{
    int len = s.size();
    if( (len <= 0)|| (len>0&&s[0]=='0'))
        return 0;
    int *dp_num = new int[len]{};
    dp_num[0] = 1;
    for (int i = 1; i < len; i++)
    {
        dp_num[i] = s[i] == '0' ? 0 : dp_num[i - 1];//选取i这一位,只取当前指向的一个数字,如果为0,dp[i-1]=0,否则,取dp[i-1]
        if (i >= 1 && (s[i - 1] == '1' || (s[i - 1] == '2'&&s[i] <= '6')))//当前数和当前数的前一个数,看看是否在10-26之间
        {
            if (i == 1)
                dp_num[i] += 1;
            else
                dp_num[i] += dp_num[i - 2];
        }
    }
    return dp_num[len - 1];
}

当然如果要输出所有的解码方式具体是怎么样,可以进行DFS,比如12125,我们选择1这个字符解码,也可以选择12进行解码,之后2125或125相当于是一个新的字符要进行解码,不断进行搜素,终止条件为到达字符串尾。代码如下:

/*
s表示原始字符串,用引用,通过下标可以获取到字符
temp 用来存储解析好的字符串,最后输出,用引用,一直记录解码后的字符,直至递归返回
start表示从第几个位置的字符开始解析
end表示s.size();
*/
void numDecodings_list(string &s,string &temp,int start,int end)
{
    int len = s.size();
    if (len <= 0 || (len > 0 && s[start] == '0'))
        return ;
    if (start == end)
    {
        num++;
        cout <<"第"<<num<<"种解码为:"<< temp << endl;
        //temp.clear();不用清除,递归后pop后自己会变为空
        return;
    }
    if (s[start] != '0')//第一个不为0
    {
        char a = s[start] - '1' + 'a';
        temp.push_back(a);
        numDecodings_list(s, temp, start + 1, end);//继续递归搜索
        temp.pop_back();//再回到第一次调用处,这里弹出后 temp=""为空,可以继续添加
        if (start+1<end&&(s[start] == '1' || (s[start] == '2'&&s[start + 1] <= '6')))//注意start+1<end
        {       
            a = (s[start] - '0') * 10 + (s[start + 1] - '1') + 'a';
            temp.push_back(a);
            numDecodings_list(s, temp, start +2, end);//继续递归搜索
            temp.pop_back();
        }
    }
}
int main(void)
{
    string s;
    string t;
    while (1)
    {
        cin >> s;
        numDecodings_list(s, t, 0, s.size());
        t.clear();
        num = 0;//全局
    }
}

输出如下:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值