我正在做一些算法练习并遇到了一个我难以解决的问题。
手机上的每个数字键代表某些字母(例如2 => A, B, C
,3 => D, E, F
等,但1
和0
除外。用户可以多次敲击键以“滚动”到不同的字母。例如,222
可以是AAA
,AB
,BA
或C
。
给定一个输入字符串,例如444223
,这代表什么不同的组合?
您可以假设有一个字典/散列图,其中包含要映射映射的数字。
map = {
2 => "ABC",
3 => "DEF",
4 => "GHI",
5 => "JKL",
6 => "MNO",
7 => "PQRS",
8 => "TUV",
9 => "WXYZ",
}
我试图分两部分来解决这个问题。首先,将输入拆分为连续数字的子串数组。例如:["444", "22", "3"]
。然后,通过递归算法运行其中的每一个,该算法将输入分解为其基本情况(例如f(4444) -> f(444) -> f(44) -> f(4)
),然后求解单个数字并返回链中计算出所有排列。
然而,我无法让它发挥作用 - 我不知道这是否是正确的方法。当数字字符串大于字母数(例如4444
)时,我也遇到了问题,因为这可能是两个B
s,我认为这不会对我尝试的置换递归算法起作用写。
任何帮助将不胜感激!
答案 0 :(得分:2)
你在正确的轨道上将相同数字的条纹分解成所有排列。
递归部分最多有三个部分。因此对于4444,第一步分为3个部分:
"4" (G) --> continue on 444
"44" (H) --> continue on 44
"444" (I) --> continue on 4
使用相同的规则继续使用剩下的字符串。
编辑:
由于数据结构的原因,写入伪代码有点复杂。你需要三件事:
因此,对于给定的相同数字序列,分区的工作原理如下:
PartitionNums (sets, curset, val, len) {
if len = 1 then
insert into sets (curset, val)
else if len = 2 then
insert into sets (curset, val)
insert into sets (curset, val||val)
else if len = 3 then
insert into sets (curset, val||val||val)
ProcessSets(sets, (curset, val), val, len - 1)
ProcessSets(sets, (curset, val||val), val, len - 2)
else
ProcessSets(sets, (curset, val), len - 1)
ProcessSets(sets, (curset, val||val), len - 2)
ProcessSets(sets, (curset, val||val||val), len - 3)
}
它会被称为:
ProcessSets({}, '', '4', 5)
对于44444。
这只处理一串相同的数字。然后必须将其编织成代码,分割字符串并从数字序列中查找字符。
答案 1 :(得分:0)
这看起来很酷,所以我在Perl中编写了一个实现。基本前提是将每组数字拆分成连续的数字,然后生成那些数字的所有可能分组,这些数字等于数字串的长度。之后,只需将数字输入映射表,并将结果分组为单个解决方案。
#!/usr/bin/env perl
use strict;
use warnings;
use Set::Product::PP qw(product);
my %digit_map = (
2 => [qw(A B C)],
3 => [qw(D E F)],
4 => [qw(G H I)],
5 => [qw(J K L)],
6 => [qw(M N O)],
7 => [qw(P Q R S)],
8 => [qw(T U V)],
9 => [qw(W X Y Z)],
);
sub decode {
my (@digits) = @_;
my $last_digit = $digits[0];
my @solutions;
my @consecutive_digits;
while ( my $digit = shift @digits ) {
if ( $digit == $last_digit ) {
push @consecutive_digits, $digit;
}
else {
$last_digit = $digit;
push @solutions, [
map { _partitions_to_letter($_) } _partitions(@consecutive_digits)
];
@consecutive_digits = ( $digit );
}
}
if ( @consecutive_digits ) {
push @solutions, [
map { _partitions_to_letter($_) } _partitions(@consecutive_digits)
];
}
my @combined_solutions;
# compute cartesian product of all partitioned consecutive digits
product { push @combined_solutions, join '', @_ } @solutions;
return @combined_solutions;
}
sub _partitions_to_letter {
my ($partitions) = @_;
return join '', map { $digit_map{ $_->[0] }->[ @$_ - 1 ] } @$partitions;
}
sub _partitions {
my (@consecutive_digits) = @_;
return [ [@consecutive_digits] ] if @consecutive_digits == 1;
my @partitions = (
# use the current array as a partition
[ [@consecutive_digits] ],
# each piece of the current array counts as a partition
[ map { [$_] } @consecutive_digits ],
);
foreach my $i ( 0 .. $#consecutive_digits - 1) {
push @partitions, [
[@consecutive_digits[0..$i]],
[@consecutive_digits[$i+1..$#consecutive_digits]]
];
}
return @partitions;
}
foreach my $solution ( decode(qw(4 4 4 2 2 3)) ) {
print $solution, "\n";
}
# IBD
# IAAD
# IAAD
# GGGBD
# GGGAAD
# GGGAAD
# GHBD
# GHAAD
# GHAAD
# HGBD
# HGAAD
# HGAAD
很高兴解释任何难以理解的作品。