给出映射:
A: 1
B: 2
C: 3
...
...
...
Z: 26
找出可以表示数字的所有可能方式。例如。对于输入:“121”,我们可以将其表示为:
ABA [using: 1 2 1]
LA [using: 12 1]
AU [using: 1 21]
我尝试过使用某种动态编程方法,但我不知道如何继续。我在技术面试中被问到这个问题。
这是我能想到的解决方案,如果这看起来不错,请告诉我:
A[i]: Total number of ways to represent the sub-array number[0..i-1] using the integer to alphabet mapping.
解决方案[我错过了什么吗?]:
A[0] = 1 // there is only 1 way to represent the subarray consisting of only 1 number
for(i = 1:A.size):
A[i] = A[i-1]
if(input[i-1]*10 + input[i] < 26):
A[i] += 1
end
end
print A[A.size-1]
答案 0 :(得分:4)
为了获得计数,动态编程方法非常简单:
A[0] = 1
for i = 1:n
A[i] = 0
if input[i-1] > 0 // avoid 0
A[i] += A[i-1];
if i > 1 && // avoid index-out-of-bounds on i = 1
10 <= (10*input[i-2] + input[i-1]) <= 26 // check that number is 10-26
A[i] += A[i-2];
如果您想要列出所有表示,动态编程并不是特别适合这种情况,您最好使用简单的递归算法。
答案 1 :(得分:2)
首先,我们需要找到一种直观的方式来列举所有可能性。我的简单结构如下所示。
let us assume a simple way to represent your integer in string format.
a1 a2 a3 a4 ....an, for instance in 121 a1 -> 1 a2 -> 2, a3 -> 1
现在,
我们需要找出在两个字符之间放置+号的可能性。 +表示字符串联。
a1 - a2 - a3 - .... - an, - shows the places where '+' can be placed. So, number of positions is n - 1, where n is the string length.
假设一个位置可能有也可能没有+符号应表示为一个位。 因此,这归结为n-1的长度可以有多少不同的位串,这显然是2 ^(n-1)。现在为了列举可能性,遍历每一个字符串并在相应位置放置右+符号以获得每个表示,
以你的例子,121
Four bit strings are possible 00 01 10 11
1 2 1
1 2 + 1
1 + 2 1
1 + 2 + 1
And if you see a character followed by a +, just add the next char with the current one and do it sequentially to get the representation,
x + y z a + b + c d
would be (x+y) z (a+b+c) d
希望它有所帮助。
你将不得不处理一些整数大小的边缘情况&gt; 26,当然。
答案 2 :(得分:1)
我认为,通过所有可能的组合进行递归遍历会很好:
mapping = {"1":"A", "2":"B", "3":"C", "4":"D", "5":"E", "6":"F", "7":"G",
"8":"H", "9":"I", "10":"J",
"11":"K", "12":"L", "13":"M", "14":"N", "15":"O", "16":"P",
"17":"Q", "18":"R", "19":"S", "20":"T", "21":"U", "22":"V", "23":"W",
"24":"A", "25":"Y", "26":"Z"}
def represent(A, B):
if A == B == '':
return [""]
ret = []
if A in mapping:
ret += [mapping[A] + r for r in represent(B, '')]
if len(A) > 1:
ret += represent(A[:-1], A[-1]+B)
return ret
print represent("121", "")
答案 3 :(得分:1)
假设您只需要计算组合数量。
假设0后跟[1,9]中的整数不是有效的连接,那么蛮力策略就是:
Count(s,n)
x=0
if (s[n-1] is valid)
x=Count(s,n-1)
y=0
if (s[n-2] concat s[n-1] is valid)
y=Count(s,n-2)
return x+y
更好的策略是使用分而治之:
Count(s,start,n)
if (len is even)
{
//split s into equal left and right part, total count is left count multiply right count
x=Count(s,start,n/2) + Count(s,start+n/2,n/2);
y=0;
if (s[start+len/2-1] concat s[start+len/2] is valid)
{
//if middle two charaters concatenation is valid
//count left of the middle two characters
//count right of the middle two characters
//multiply the two counts and add to existing count
y=Count(s,start,len/2-1)*Count(s,start+len/2+1,len/2-1);
}
return x+y;
}
else
{
//there are three cases here:
//case 1: if middle character is valid,
//then count everything to the left of the middle character,
//count everything to the right of the middle character,
//multiply the two, assign to x
x=...
//case 2: if middle character concatenates the one to the left is valid,
//then count everything to the left of these two characters
//count everything to the right of these two characters
//multiply the two, assign to y
y=...
//case 3: if middle character concatenates the one to the right is valid,
//then count everything to the left of these two characters
//count everything to the right of these two characters
//multiply the two, assign to z
z=...
return x+y+z;
}
蛮力解决方案的时间复杂度为T(n)=T(n-1)+T(n-2)+O(1)
,这是指数级的。
分而治之的解决方案的时间复杂度为T(n)=3T(n/2)+O(1)
,即O(n ** lg3)。
希望这是正确的。
答案 4 :(得分:1)
这样的东西?
Haskell代码:
import qualified Data.Map as M
import Data.Maybe (fromJust)
combs str = f str [] where
charMap = M.fromList $ zip (map show [1..]) ['A'..'Z']
f [] result = [reverse result]
f (x:xs) result
| null xs =
case M.lookup [x] charMap of
Nothing -> ["The character " ++ [x] ++ " is not in the map."]
Just a -> [reverse $ a:result]
| otherwise =
case M.lookup [x,head xs] charMap of
Just a -> f (tail xs) (a:result)
++ (f xs ((fromJust $ M.lookup [x] charMap):result))
Nothing -> case M.lookup [x] charMap of
Nothing -> ["The character " ++ [x]
++ " is not in the map."]
Just a -> f xs (a:result)
输出:
*Main> combs "121"
["LA","AU","ABA"]
答案 5 :(得分:0)
只是我们广度优先搜索。
例如121
从第一个整数开始, 首先考虑1个整数字符,将1映射到a,留下21 然后2个整数字符映射12到L离开1。
答案 6 :(得分:0)
以下是基于我在此讨论的解决方案:
private static int decoder2(int[] input) {
int[] A = new int[input.length + 1];
A[0] = 1;
for(int i=1; i<input.length+1; i++) {
A[i] = 0;
if(input[i-1] > 0) {
A[i] += A[i-1];
}
if (i > 1 && (10*input[i-2] + input[i-1]) <= 26) {
A[i] += A[i-2];
}
System.out.println(A[i]);
}
return A[input.length];
}
答案 7 :(得分:0)
使用标准DP算法可以在o(fib(n + 2))时间内完成此问题。 我们有n个子问题和按钮我们可以用o(fib(i))时间解决尺寸i的每个问题。 对该系列求和得到fib(n + 2)。
如果你仔细考虑这个问题,你会发现它是斐波那契系列。 我采用了标准的Fibonacci代码,并根据我们的条件进行了更改。
空间显然与所有解决方案的大小有关(fib(n))。
考虑这个伪代码:
Map<Integer, String> mapping = new HashMap<Integer, String>();
List<String > iterative_fib_sequence(string input) {
int length = input.length;
if (length <= 1)
{
if (length==0)
{
return "";
}
else//input is a-j
{
return mapping.get(input);
}
}
List<String> b = new List<String>();
List<String> a = new List<String>(mapping.get(input.substring(0,0));
List<String> c = new List<String>();
for (int i = 1; i < length; ++i)
{
int dig2Prefix = input.substring(i-1, i); //Get a letter with 2 digit (k-z)
if (mapping.contains(dig2Prefix))
{
String word2Prefix = mapping.get(dig2Prefix);
foreach (String s in b)
{
c.Add(s.append(word2Prefix));
}
}
int dig1Prefix = input.substring(i, i); //Get a letter with 1 digit (a-j)
String word1Prefix = mapping.get(dig1Prefix);
foreach (String s in a)
{
c.Add(s.append(word1Prefix));
}
b = a;
a = c;
c = new List<String>();
}
return a;
}
答案 8 :(得分:0)
旧问题,但添加了一个答案,以便人们可以找到帮助
我花了一些时间来理解该问题的解决方案–我从geeksforgeeks引用了可接受的答案和@Karthikeyan的答案以及解决方案,并编写了自己的代码,如下所示:
要了解我的代码,请先了解以下示例:
decodings([1, 2])
是"AB"
或"L"
,所以decoding_counts([1, 2]) == 2
decodings([1, 2, 1])
是"ABA"
,"AU"
,"LA"
,所以decoding_counts([1, 2, 1]) == 3
使用以上两个示例,我们来评估decodings([1, 2, 1, 4])
:
情况:-“以下一位数字为一位”
将4
作为一个数字解码为字母'D'
,我们得到 decodings([1, 2, 1, 4])
== decoding_counts([1, 2, 1])
,因为[1, 2, 1, 4]
将被解码为"ABAD"
,"AUD"
,"LAD"
情况:-“将下一位与前一位相结合”
将4
与先前的1
合并为14
并作为单个字母解码为字母N
,我们得到 decodings([1, 2, 1, 4])
== {{1 }} ,因为decoding_counts([1, 2])
将被解码为[1, 2, 1, 4]
或"ABN"
下面是我的Python代码,请阅读注释
"LN"
输出:
def decoding_counts(digits):
# defininig count as, counts[i] -> decoding_counts(digits[: i+1])
counts = [0] * len(digits)
counts[0] = 1
for i in xrange(1, len(digits)):
# case:- "taking next digit as single digit"
if digits[i] != 0: # `0` do not have mapping to any letter
counts[i] = counts[i -1]
# case:- "combining next digit with the previous digit"
combine = 10 * digits[i - 1] + digits[i]
if 10 <= combine <= 26: # two digits mappings
counts[i] += (1 if i < 2 else counts[i-2])
return counts[-1]
for digits in "13", "121", "1214", "1234121":
print digits, "-->", decoding_counts(map(int, digits))
注意:我假设输入13 --> 2
121 --> 3
1214 --> 5
1234121 --> 9
不是以digits
开头,而是仅由0
组成,并且长度足够
答案 9 :(得分:0)
经过研究,我偶然发现了这段视频https://www.youtube.com/watch?v=qli-JCrSwuk,解释得很好。
答案 10 :(得分:0)
对于Swift,这就是我想出的。基本上,我将字符串转换为数组并遍历整个数组,在该数组的不同位置添加一个空格,然后将它们附加到第二部分的另一个数组中,这样做很容易。
//test case
let input = [1,2,2,1]
func combination(_ input: String) {
var arr = Array(input)
var possible = [String]()
//... means inclusive range
for i in 2...arr.count {
var temp = arr
//basically goes through it backwards so
// adding the space doesn't mess up the index
for j in (1..<i).reversed() {
temp.insert(" ", at: j)
possible.append(String(temp))
}
}
print(possible)
}
combination(input)
//prints:
//["1 221", "12 21", "1 2 21", "122 1", "12 2 1", "1 2 2 1"]