LeetCode第[91]题(Java):Decode Ways(解码方法数)

题目:解码方法数

难度:Medium

题目内容

A message containing letters from A-Z is being encoded to numbers using the following mapping:

‘A‘ -> 1
‘B‘ -> 2
...
‘Z‘ -> 26

Given a non-empty string containing only digits, determine the total number of ways to decode it.

翻译

一个包含A-Z字母的消息被编码成数字,使用以下映射:

“A” - > 1

“B”- > 2

……

“Z”- > 26

给定一个包含数字的非空字符串,确定解码它的总方法数。

我的思路:一开始想用递归但是边界问题太多,就放弃了。

      single 从0开始(每个数组单独解码),count从1开始,如果s[i-1]s[i]二者组成的数字在(0,26 ] 范围内,那就count+;

      且遇见0的时候,一开始的单独编码就不存在了,且少了一次组合的机会,例如【110】 中【11】和【0】不能组合

        所以此时 single = 0;count - 1

我的代码

 1     public int numDecodings(String s) {
 2         if (s.isEmpty() || s.charAt(0) == ‘0‘)
 3             return 0;
 4
 5         int count = 0;
 6         int single = 1;
 7         for (int i = 1; i < s.length(); i++) {
 8             if (s.charAt(i) == ‘0‘){
 9                 count = s.length() > 2 ? count-1 : count;
10                 single = 0;
11             }
12             int x = Integer.parseInt(s.substring(i-1, i+1));
13             if ( x<= 26 && x > 0) {
14                 count += 1;
15             }
16         }
17         return (count + single) > 0 ? (count + single) : 0;
18     }

结果:214 / 258 test cases passed.

Input:"1212"

Output:4

Expected:5

编码过程中的问题

1、最初 single 和 count 没有分开计算;

2、第9行,当只有两个的时候,此时count 不需要 -1 ,例如【10】;

3、这个思路还是有问题的,例如【1212】中少计算了【12】【12】这个组合

答案代码

 1 public class Solution {
 2     public int numDecodings(String s) {
 3         int n = s.length();
 4         if (n == 0) return 0;
 5
 6         int[] memo = new int[n+1];
 7         memo[n]  = 1;
 8         memo[n-1] = s.charAt(n-1) != ‘0‘ ? 1 : 0;
 9
10         for (int i = n - 2; i >= 0; i--)
11             if (s.charAt(i) == ‘0‘) continue;
12             else memo[i] = (Integer.parseInt(s.substring(i,i+2))<=26) ? memo[i+1]+memo[i+2] : memo[i+1];
13
14         return memo[0];
15     }
16 }

答案思路

假设所有的数字都有效,且左右两两相邻数之间也有效(1到26),那么有如下规律

   numDecodings(s) = numDecodings(s.substring(1)) + numDecodings(s.substring(2)) --------------------------------------------------式(1)

规律显而易见,斐波那契数列。不过是反过来的(从字符串后面往前)

当然,那只是假设,也要考虑特殊情况:

【使用一个数组(大小为len+1)从后往前记录对应的数字“出现”后解码数的增量

1、当前指针所指字符为0

  此时此字符无法解码,所以式(1)中的前者就只能为0,后者也为0

  例如【023】,substring(1)——【0】|【23】,截掉的【0】不能解析,所以此组合无效

         substring(2)——【02】|【3】,截掉的【02】不能解析,所以此组合无效

  所以0数字出现后,解码数的增量为0。

2、当前字符的值是有效的(大于0),但是当前字符与右边字符组合的数字无效(大于26)

  相当于式(1)中的后者=0

  例如【3212】,substring(1)——【3】|【212】,截掉的【3】能解析,所以其值为【212】的解码数

         substring(2)——【32】|【12】,截掉的【32】不能解析,所以此组合无效\

递归实现:

 1     public int numDecodings(String s) {
 2         if (s.isEmpty()) {
 3             return 1;
 4         }
 5
 6         if (s.charAt(0) == ‘0‘) {
 7             return 0;
 8         }
 9
10         if (s.length() == 1)
11             return 1;
12
13         int sub1 = numDecodings(s.substring(1));
14         int sub2 = 0;
15
16         if (Integer.parseInt(s.substring(0,2)) <= 26) {
17             sub2 = numDecodings(s.substring(2));
18         }
19         return sub1 + sub2;
20     }

此方法会在最后几个用例(很长)运行超时。

所以答案采用了迭代的方式进行。

优化:既然是斐波纳数列,那么就能使用双值迭代的方式取代用一个数组进行记录。

 1     public int numDecodings(String s) {
 2         if (s.isEmpty() || s.charAt(0) == ‘0‘) {
 3             return 0;
 4         }
 5         int sub1 = 1;
 6         int sub2 = 1;
 7         for (int i = s.length() - 2; i > -1; i--) {
 8             if (s.charAt(i+1) == ‘0‘) {
 9                 sub1 = 0;
10             }
11             if (Integer.parseInt(s.substring(i,i+2)) <= 26) {
12                 sub1 = sub1 + sub2;
13                 sub2 = sub1 - sub2;
14             } else {
15                 sub2 = sub1;
16             }
17         }
18         return sub1;
19     }

第11行其实还可以使用字符进行判断以降低时间和空间复杂度:

   s.charAt(i) == ‘1‘ || s.charAt(i) == ‘2‘ && s.charAt(i+1) - ‘0‘ <= 6

原文地址:https://www.cnblogs.com/Xieyang-blog/p/9107432.html

时间: 2024-10-10 08:44:10

LeetCode第[91]题(Java):Decode Ways(解码方法数)的相关文章

Leetcode 91. Decode Ways 解码方法(动态规划,字符串处理)

Leetcode 91. Decode Ways 解码方法(动态规划,字符串处理) 题目描述 一条报文包含字母A-Z,使用下面的字母-数字映射进行解码 'A' -> 1 'B' -> 2 ... 'Z' -> 26 给一串包含数字的加密报文,求有多少种解码方式 举个例子,已知报文"12",它可以解码为AB(1 2),也可以是L (12) 所以解码方式有2种. 测试样例 Input: "0" "121212" "1010

[LeetCode] 91. Decode Ways 解码方法

A message containing letters from A-Z is being encoded to numbers using the following mapping: 'A' -> 1 'B' -> 2 ... 'Z' -> 26 Given an encoded message containing digits, determine the total number of ways to decode it. For example,Given encoded

leetCode 91.Decode Ways (解码方式) 解题思路和方法

A message containing letters from A-Z is being encoded to numbers using the following mapping: 'A' -> 1 'B' -> 2 ... 'Z' -> 26 Given an encoded message containing digits, determine the total number of ways to decode it. For example, Given encoded

[LeetCode] decode ways 解码方式

A message containing letters fromA-Zis being encoded to numbers using the following mapping: 'A' -> 1 'B' -> 2 ... 'Z' -> 26 Given an encoded message containing digits, determine the total number of ways to decode it. For example,Given encoded me

[LeetCode][Java] Decode Ways

题目: A message containing letters from A-Z is being encoded to numbers using the following mapping: 'A' -> 1 'B' -> 2 ... 'Z' -> 26 Given an encoded message containing digits, determine the total number of ways to decode it. For example, Given enc

[LeetCode] Decode Ways 解码方法

A message containing letters from A-Z is being encoded to numbers using the following mapping: 'A' -> 1 'B' -> 2 ... 'Z' -> 26 Given an encoded message containing digits, determine the total number of ways to decode it. For example,Given encoded

[LintCode] Decode Ways 解码方法

A message containing letters from A-Z is being encoded to numbers using the following mapping: 'A' -> 1'B' -> 2...'Z' -> 26Given an encoded message containing digits, determine the total number of ways to decode it. ExampleGiven encoded message 1

LeetCode第[26]题(Java):Remove Duplicates from Sorted Array 标签:Array

题目难度:Easy 题目: Given a sorted array, remove the duplicates in-place such that each element appear only once and return the new length. Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extr

LeetCode第[5]题(Java):Longest Palindromic Substring 标签:String、动态规划

题目中文:求最长回文子串 题目难度:Medium 题目内容: Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000. 翻译: 给定一个字符串s,找出s中最长的回文子串.你可以假设s的最大长度是1000. 什么叫回文子串? 就是字符串中,满足能正读反读都一样的子串,就是回文子串.如下所示 Input: "babad"