class Solution { private static final int EMPTY = -1; private static int charToDigit(String s, int i) { return s.charAt(i) - '0'; } private int numDecodings(String s, int[] dp, int i) { // out of bounds if (i < 0 || i > s.length()) { return 0; } // final digit if (i == s.length()) { return 1; } // starting with 0, not allowed if (s.charAt(i) == '0') { return 0; } // solution has been already precomputed if (dp[i] != EMPTY) { return dp[i]; } // taking just one digit int result = numDecodings(s, dp, i + 1); // taking two digits if (i + 1 < s.length() && charToDigit(s, i) * 10 + charToDigit(s, i + 1) <= 26) { result += numDecodings(s, dp, i + 2); } // save and return dp[i] = result; return result; } public int numDecodings(String s) { int[] dp = new int[s.length()]; for (int i = 0; i < dp.length; ++i) { dp[i] = EMPTY; } return numDecodings(s, dp, 0); } }