想象一下,我有一袋26个拼字游戏瓷砖 - 英文字母中每个字母一个。
我的目标是创建一个包含最长n
个字母的所有可能字符串的数组。说n=3
。
约束:
ABC
,而不是CBA
;组合,而不是排列)n
个字母长(允许算法突破给定长度的任何循环)A
,而不是AA
)如何在PHP中最有效地生成此数组?
换句话说,我如何避免强制循环所有可能的组合并过滤掉那些与上述规则不符的内容?
如果我的字母只包含3个字母 - $alphabet = range('a','c');
- 我希望输出7个项目(3C1 + 3C2 + 3C3)的数组:[A,B,C,AB,AC,BC,ABC]
。
如果我的字母只包含4个字母 - $alphabet = range('a','d');
- 我希望输出15个项目(4C1 + 4C2 + 4C3 + 4C4)的数组:[A,B,C,D,AB,AC,AD,BC,BD,CD,ABC,ABD,ACD,BCD,ABCD]
。但是如果我想限制只用<= 3
个字符串长,那么我会忽略ABCD
只产生14个项目(4C1 + 4C2 + 4C3)。
$alphabet = range('a','z');
print_r(generate_strings($alphabet,1));
// expected output: A,B,C,...Z
print_r(generate_strings($alphabet,2));
// expected output: A..Z, AB..AZ, BC..BZ, CD, ..YZ
print_r(generate_strings($alphabet,3));
// expected output: A..Z, AB..YZ, ABC..XYZ
print_r(generate_strings($alphabet,10));
// expected output: A .. JKLMN .. AGKQRZ .. QRSTUVWXYZ
// ^ ^ ^10 character max, no repeats
// | still alphabetical order
// alphabetical order
function generate_strings($alphabet,$max_word_length) {
// how can I efficiently generate this array
// without brute force looping through all of
// the invalid and duplicate items like AA and CBA?
return $array_of_all_possible_strings;
}
答案 0 :(得分:2)
我认为这看起来很有趣。这是我对它的尝试,因为它值得:
function recurse($letters, &$words, $start, $end, $depth, $prefix = "") {
$depth--;
for ($i = $start; $i < $end; $i++) {
$word = $prefix . $letters[$i];
$words[] = $word;
if ($depth) recurse($letters, $words, ++$start, $end, $depth, $word);
}
}
function generate_strings($letters, $max_word_length) {
$words = array();
recurse($letters, $words, 0, count($letters), $max_word_length);
return $words;
}
答案 1 :(得分:1)
不知道php,但算法很明确:
答案 2 :(得分:0)
我今天编辑了this similar post(因为我意识到我最初发布了一个不正确的方法),在研究这个主题时,我发现你的问题很有趣。
在我能说的时候,不能使用LeavePanic的递归方法。我只是想我会发布一个基于我的链接方法的非递归“堆叠”方法。我相信我们的解决方案之间几乎没有性能差异,也许你会发现我的解决方案更容易阅读(也许不是)。
代码:(Demo)
function permStacker($array,$length){
$stack=[[]]; // declare intitial empty element
for($x=0; $x<$length; ++$x){ // limit the total number of passes / max string length
foreach($stack as $combination){
foreach(array_diff($array,range('a',end($combination))) as $left){ // do not include iterate letter that come earlier than rightmost letter
$merge=array_merge($combination,[$left]);
$stack[implode($merge)]=$merge; // keys hold desired strings, values hold subarray of combinations for iterated referencing
}
}
}
unset($stack[0]); // remove initial empty element
return array_keys($stack); // return array of permutations as space delimited strings
}
$permutations=permStacker(range('a','h'),4);
echo 'Total Permutations: ',sizeof($permutations),"\n";
var_export($permutations);
输出(截断):
Total Permutations: 162
array (
0 => 'a',
1 => 'b',
2 => 'c',
3 => 'd',
4 => 'e',
5 => 'f',
6 => 'g',
7 => 'h',
8 => 'ab',
9 => 'ac',
10 => 'ad',
11 => 'ae',
12 => 'af',
13 => 'ag',
14 => 'ah',
15 => 'bc',
16 => 'bd',
17 => 'be',
18 => 'bf',
19 => 'bg',
20 => 'bh',
21 => 'cd',
22 => 'ce',
23 => 'cf',
24 => 'cg',
25 => 'ch',
26 => 'de',
...
126 => 'afgh',
127 => 'bcde',
128 => 'bcdf',
129 => 'bcdg',
130 => 'bcdh',
131 => 'bcef',
132 => 'bceg',
133 => 'bceh',
134 => 'bcfg',
135 => 'bcfh',
136 => 'bcgh',
137 => 'bdef',
138 => 'bdeg',
139 => 'bdeh',
140 => 'bdfg',
141 => 'bdfh',
142 => 'bdgh',
143 => 'befg',
144 => 'befh',
145 => 'begh',
146 => 'bfgh',
147 => 'cdef',
148 => 'cdeg',
149 => 'cdeh',
150 => 'cdfg',
151 => 'cdfh',
152 => 'cdgh',
153 => 'cefg',
154 => 'cefh',
155 => 'cegh',
156 => 'cfgh',
157 => 'defg',
158 => 'defh',
159 => 'degh',
160 => 'dfgh',
161 => 'efgh',
)