解码方法( dfs | dp )

解码方法

详情参见leetcode 91.解码方法

我的解法:

在这里插入图片描述
dfs深度遍历优先搜索,遇到错误情况返回。

错误情况包含以下三种:

  1. 单个为0或者两个字符以0为前导;
  2. 两个字符的值大于26 即不为A~Z;
  3. 整个字符转含有前导0。

但是因为字符串长度为 1 ≤ length ≤ 1000,采用dfs的开销太大,超出时间限制,故不可取。

代码如下:

class Solution {
public:
    int answer=0;//计数
    string str;//全局存储

    void dfs(int cur) {
        if(cur>=str.size()) {
            answer++;
            return;
        }
        if(str[cur]=='0') return;
        dfs(cur+1);//第一种情况
        if(cur<=str.size()-2) {//第二种情况
            if( (str[cur]-'0')*10 + (str[cur+1]-'0') <= 26 ) {
                dfs(cur+2);
            }
        }
        return;
    }

    int numDecodings(string s) {
        str=s;
        if(str[0]=='0') return 0;//当含有前导0时 返回0
        if(str.size()==1) return 1;//仅含有一个数据元素时
        dfs(1);
        if( (str[0]-'0')*10 + (str[1]-'0') <= 26) {//不超过限制时
            dfs(2);
        }
        return answer;
    }
};

动态规划解法:

对于一个确定的字符串 s 而言,当在其后添加一个字符后,按照题目要求存在的情况,

其能组成的所有可能为:s 的所有情况 + ( s - s [length-1] )的所有情况 (当然还有排除不存在的情况)

不妨设:s 的长度为n,并且从左至右的字符串分别为 s [1] 、s [2] …s[n];

故我们可以使用动态规划的方法,计算出每一个 s [ i ] 阶段所含有的满足题意的解码方法数。

由最开始的描述,具体地,设 f [ i ] 表示字符串 s 的前 i 个字符 s[1…i] 的解码方法数。

在进行状态转移时,我们可以考虑最后一次解码使用了 s 中的哪些字符,那么会有下面的两种情况:

  • 如果 s [ i ] ≠ 0,那么它就可以被单独分解,故 f [ i ] = f [ i - 1 ];
  • 对 s [ i - 1] 和 s [ i ]进行组合编码,并且s [ i - 1] ≠ 0 和 二者组成的字符串不能大于26,故f [ i ] = f [ i - 2 ];

动态规划的边界条件设置为 f [ 0 ] = 1,空字符串也是一种可能 (因为 length≥1 )

class Solution {
    public int numDecodings(String s) {
        int n = s.length();
        int[] f = new int[n + 1];
        f[0] = 1;//动态规划的边界条件
        for (int i = 1; i <= n; ++i) {
            if (s.charAt(i - 1) != '0') {
                f[i] += f[i - 1];//单个字符情况
            }
            if (i>1 && s.charAt(i-2) != '0' && ((s.charAt(i-2)-'0') * 10 + (s.charAt(i-1)-'0') <= 26)) {
                f[i] += f[i - 2];//双个字符情况
            }
        }
        return f[n];
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值