我在项目中使用了更大的数组,但为了简化起见,假设我们有一个3x3数组:
if(getIntent() != null){
String path = getIntent().getStringExtra("image");
Glide.with(this)
.load(path)
.into(imageView);
}
我想找到每行包括一个值的总和的每种组合,即1 + 4 + 7、1 + 4 + 8、1 + 4 + 9、1 + 5 + 7、1 + 5 + 8 ,1 + 5 + 9,1 + 6 + 7,1 + 6 + 8,1 + 6 + 9,2 + 4 + 7,2 + 4 + 8,2 + 4 + 9,2 + 5 + 7,。 ..
希望这种模式很明显。我先尝试了一个嵌套循环(列,然后是行),但是并没有提供所有组合。经过大量搜索之后,我对解决方案需要递归感到很有信心,但是每次尝试为此编写递归函数时,我都会感到困惑。
虽然非常感谢工作代码,但对我来说更重要的是了解问题和解决方案。
答案 0 :(得分:2)
给出数组中未知数量的行和列,获得所需结果的最佳方法是使用递归(否则,您将必须编写任意数量的嵌套循环)。此函数在数组的每一行上递归,并返回两个结果之一:
foreach
循环)。我们使用array_shift
来获取当前行,并将其从数组中删除。代码如下:
function find_paths($array) {
if (count($array) == 1) return $array[0];
$output = array();
foreach (array_shift($array) as $v1) {
foreach (find_paths($array) as $v2) {
$output[] = array_merge(array($v1), is_array($v2) ? $v2 : array($v2));
}
}
return $output;
}
使用示例数据:
$a = Array( Array(1,2,3),
Array(4,5,6),
Array(7,8,9) );
$combinations = find_paths($a);
该函数执行以下一系列操作:
(1, 2, 3)
的叉积与函数输出的结果相乘,得到数组((4, 5, 6), (7, 8, 9))
的余额; (4, 5, 6)
的叉积与函数输出((7, 8, 9))
的叉积相乘; (7, 8, 9)
中仅剩一行,因此我们将其返回; (4, 5, 6)
与(7, 8, 9)
= ((4, 7), (4, 8), (4, 9), (5, 7), (5, 8), (5, 9), (6, 7), (6, 8), (6, 9))
的叉积并返回; (1, 2, 3)
与((4, 7), (4, 8), (4, 9), (5, 7), (5, 8), (5, 9), (6, 7), (6, 8), (6, 9))
的叉积,并将其返回。提供以下输出:
Array (
[0] => Array ( [0] => 1 [1] => 4 [2] => 7 )
[1] => Array ( [0] => 1 [1] => 4 [2] => 8 )
[2] => Array ( [0] => 1 [1] => 4 [2] => 9 )
[3] => Array ( [0] => 1 [1] => 5 [2] => 7 )
[4] => Array ( [0] => 1 [1] => 5 [2] => 8 )
[5] => Array ( [0] => 1 [1] => 5 [2] => 9 )
[6] => Array ( [0] => 1 [1] => 6 [2] => 7 )
[7] => Array ( [0] => 1 [1] => 6 [2] => 8 )
[8] => Array ( [0] => 1 [1] => 6 [2] => 9 )
[9] => Array ( [0] => 2 [1] => 4 [2] => 7 )
[10] => Array ( [0] => 2 [1] => 4 [2] => 8 )
[11] => Array ( [0] => 2 [1] => 4 [2] => 9 )
[12] => Array ( [0] => 2 [1] => 5 [2] => 7 )
[13] => Array ( [0] => 2 [1] => 5 [2] => 8 )
[14] => Array ( [0] => 2 [1] => 5 [2] => 9 )
[15] => Array ( [0] => 2 [1] => 6 [2] => 7 )
[16] => Array ( [0] => 2 [1] => 6 [2] => 8 )
[17] => Array ( [0] => 2 [1] => 6 [2] => 9 )
[18] => Array ( [0] => 3 [1] => 4 [2] => 7 )
[19] => Array ( [0] => 3 [1] => 4 [2] => 8 )
[20] => Array ( [0] => 3 [1] => 4 [2] => 9 )
[21] => Array ( [0] => 3 [1] => 5 [2] => 7 )
[22] => Array ( [0] => 3 [1] => 5 [2] => 8 )
[23] => Array ( [0] => 3 [1] => 5 [2] => 9 )
[24] => Array ( [0] => 3 [1] => 6 [2] => 7 )
[25] => Array ( [0] => 3 [1] => 6 [2] => 8 )
[26] => Array ( [0] => 3 [1] => 6 [2] => 9 )
)
如果您随后想要获取总和,则可以简单地在数组上使用array_map
,调用array_sum
以获取每个元素的总和:
$sums = array_map(function ($v) { return array_sum($v);}, $combinations);
输出:
Array (
[0] => 12
[1] => 13
[2] => 14
[3] => 13
[4] => 14
[5] => 15
[6] => 14
[7] => 15
[8] => 16
[9] => 13
[10] => 14
[11] => 15
[12] => 14
[13] => 15
[14] => 16
[15] => 15
[16] => 16
[17] => 17
[18] => 14
[19] => 15
[20] => 16
[21] => 15
[22] => 16
[23] => 17
[24] => 16
[25] => 17
[26] => 18
)
答案 1 :(得分:1)
修改了一段时间后,我发现了另一个解决方案,该解决方案比尼克的解决方案或我的原始答案都快得多,并且占用的内存更少。当使用更大和更多的阵列时,这一点很重要。例如,尝试使用9 x 9(1.34亿个组合)代替3 x 3(27个组合)。
尼克提供的代码不仅可以按要求工作,而且可以得到很好的解释,仍然值得接受。另外,此代码借鉴了Nick的一些逻辑。
性能窍门是,我们只求和而不是找到所有组合然后求和。这样,我们就不会创建潜在的大型阵列,而只是创建一个潜在的大型阵列。
编辑:通过引用传递$sums
而不是使用array_merge
可以节省更多的时间和内存。代码已更新。
function combo_sums($arrays, $sum = 0, &$sums = []) {
$array = array_shift($arrays);
if (count($arrays) > 0)
foreach ($array as $value)
combo_sums($arrays, $sum + $value, $sums);
else
foreach ($array as $value)
$sums[] = $sum + $value; # These are the final sums.
return $sums;
}
答案 2 :(得分:0)
更多搜索后,我在这里找到了解决方案:https://gist.github.com/cecilemuller/4688876
我使用上面的示例数据对其进行了测试,它提供了所需的确切组合。如预期的那样,使用array_map
按照尼克的答案查找总和。
令我惊讶的是,它不依赖于递归,而是三个嵌套循环。希望我能全神贯注于它的工作原理。