2020-02-06 java_递归_动态规划

leetcode——091

作者:reedfan

链接:https://leetcode-cn.com/problems/decode-ways/solution/java-di-gui-dong-tai-gui-hua-kong-jian-ya-suo-by-r/

来源:力扣(LeetCode)

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

解析

递归和动态规划两种解法。本题解讲述如何从递推转换成动态规划。

从后往前遍历。如果

以22067为例,从后往前遍历。

首先如果为7。很显然是1种7->G

如果为67。很显然还是1种67->FG

如果为067。结果为0。

如果为2067。 结果为numDecodings(20 67)+ numDecodings(2 067)= numDecodings(20 67)->TFG

如果为22067。 结果为numDecodings(2 2067)+ numDecodings(22 067)= numDecodings(2 2067)->BTFG

从中,我们可以看出规律。

如果开始的数为0,结果为0。

如果开始的数加上第二个数小于等于26。结果为 numDecodings(start+1)+ numDecodings(start +2)

如果开始的数加上第二个数大于26。结果为 numDecodings(start +1)

public int numDecodings(String s) {

        if (s == null || s.length() == 0) {

            return 0;

        }

        return digui(s, 0);

    }

//递归的套路,加一个index控制递归的层次

    private int digui(String s, int start) {

        //递归的第一步,应该是加终止条件,避免死循环。

        if (s.length() == start) {

            return 1;

        }

        //以0位开始的数是不存在的

        if (s.charAt(start) == '0') {

            return 0;

        }

        //递归的递推式应该是如果index的后两位小于等于26, 

        // digui(s, start) = digui(s, start+1)+digui(s, start+2) 

        // 否则digui(s, start) = digui(s, start+1)

        int ans1 = digui(s, start + 1);

        int ans2 = 0;

        if (start < s.length() - 1) {

            int ten = (s.charAt(start) - '0') * 10;

            int one = (s.charAt(start + 1) - '0');

            if (ten + one <= 26) {

                ans2 = digui(s, start + 2);

            }

        }

        return ans1 + ans2;

    }

递归解法存在大量的重复计算从中可以看出,在计算中进行了大量的重复计算,因此。可以想办法将重叠子问题记录下来,避免重复计算。

引入一个数组dp[],用来记录以某个字符为开始的解码数。动态规划其实就是一个填表的过程。整个过程的目标就是要填好新增的dp[]数组。


public int numDecodings(String s) {

        if (s == null || s.length() == 0) {

            return 0;

        }

        int len = s.length();

        int[] dp = new int[len + 1];

        dp[len] = 1;

        if (s.charAt(len - 1) == '0') {

            dp[len - 1] = 0;

        } else {

            dp[len - 1] = 1;

        }

        for (int i = len - 2; i >= 0; i--) {

            if (s.charAt(i) == '0') {

                dp[i] = 0;

                continue;

            }

            if ((s.charAt(i) - '0') * 10 + (s.charAt(i + 1) - '0') <= 26) {

                dp[i] = dp[i + 1] + dp[i + 2];

            } else {

                dp[i] = dp[i + 1];

            }

        }

        return dp[0];

    }

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容