简体   繁体   中英

Python: How to find all ways to decode a string?

I'm trying to solve this problem but it fails with input "226".

Problem : A message containing letters from AZ 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.

My Code:

class Solution:
    def numDecodings(self, s: str) -> int:
        decode =[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]
        ways = []
        for d in decode:
            for i in s:
                if str(d) == s or str(d) in s:
                    ways.append(d)
                if int(i) in decode:
                    ways.append(str(i))
        return len(ways)

My code returns 2. It only takes care of combinations (22,6) and (2,26).

It should be returning 3, so I'm not sure how to take care of the (2,2,6) combination.

Looks like this problem can be broken down into many subproblems thus can be solved recursively

  1. Subproblem 1 = when the last digit of the string is valid ( ie non zero number ) for that you can just recur for (n-1) digits left
if s[n-1] > "0":  
        count = number_of_decodings(s,n-1)
  1. Subproblem 2 = when last 2 digits form a valid number ( less then 27 ) for that you can just recur for remaining (n-2) digits
if (s[n - 2] == '1' or (s[n - 2] == '2' and s[n - 1] < '7') ) :  
        count += number_of_decodings(s, n - 2) 
  1. Base Case = length of the string is 0 or 1
if n == 0 or n == 1 :  
        return 1

EDIT: A quick searching on internet , I found another ( more interesting ) method to solve this particular problem which uses dynamic programming to solve this problem

# A Dynamic Programming based function 
# to count decodings  
def countDecodingDP(digits, n):  
  
    count = [0] * (n + 1); # A table to store  
                           # results of subproblems  
    count[0] = 1;  
    count[1] = 1;  
  
    for i in range(2, n + 1):  
  
        count[i] = 0;  
  
        # If the last digit is not 0, then last 
        # digit must add to the number of words  
        if (digits[i - 1] > '0'):  
            count[i] = count[i - 1];  
  
        # If second last digit is smaller than 2 
        # and last digit is smaller than 7, then 
        # last two digits form a valid character  
        if (digits[i - 2] == '1' or 
           (digits[i - 2] == '2' and 
            digits[i - 1] < '7') ):  
            count[i] += count[i - 2];  
  
    return count[n];  

the above solution solves the problem in complexity of O(n) and uses the similar method as that of fibonacci number problem

source: https://www.geeksforgeeks.org/count-possible-decodings-given-digit-sequence/

This seemed like a natural for recursion. Since I was bored, and the first answer didn't use recursion and didn't return the actual decodings, I thought there was room for improvement. For what it's worth...

def encodings(str, prefix = ''):
    encs = []
    if len(str) > 0:
        es = encodings(str[1:], (prefix + ',' if prefix else '') + str[0])
        encs.extend(es)
        if len(str) > 1 and int(str[0:2]) <= 26:
            es = encodings(str[2:], (prefix + ',' if prefix else '') + str[0:2])
            encs.extend(es)
    return encs if len(str) else [prefix]

This returns a list of the possible decodings. To get the count, you just take the length of the list. Here a sample run:

encs = encodings("123")
print("{} {}".format(len(encs), encs))

with result:

3 ['1,2,3', '1,23', '12,3']

Another sample run:

encs = encodings("123123")
print("{} {}".format(len(encs), encs))

with result:

9 ['1,2,3,1,2,3', '1,2,3,1,23', '1,2,3,12,3', '1,23,1,2,3', '1,23,1,23', '1,23,12,3', '12,3,1,2,3', '12,3,1,23', '12,3,12,3']

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM