找到 x^n 的所有组合,并检查它们的总和是否等于一个不包括相同数字的数字

Find all combinations for x^n and check if they add up to a number excluding same numbers

本文关键字:数字 是否 不包括 于一个 检查 组合 找到      更新时间:2023-10-16

所以我正在寻找一个程序,它遍历数组的所有索引组合,并检查数组中是否有相应的数字加起来是一个特定的数字(例如,有 2 个索引:array[0 到 10] + array[1 到 10] == 数字?它应该排除具有相同索引的组合,最好也排除仅具有其他顺序的组合(例如,仅 1,2 而不是 2,1(。当它找到这样的组合时,它应该保存正确的索引。 我的解决方案是使用 for 循环来做到这一点,但随后我必须为每个额外的索引创建一个新的 for 循环,这对于大约 40 个索引来说非常乏味。下面是C++中的一个示例:

//3 indices
for (int i = 0; i < iter - 2 && canWork == false; i++) {
for (int k = i + 1; k < iter - 1 && canWork == false; k++) {
for (int l = k + 1; l < iter && canWork == false; l++) {
if (sizes[i] + sizes[k] + sizes[l] == number) {
indices[0] = i;
indices[1] = k;
indices[2] = l;
canWork = true;
}
}
}
}
//4 indices
for (int i = 0; i < sizeArray - 3 && canWork == false; i++) {
for (int k = i + 1; k < sizeArray - 2 && canWork == false; k++) {
for (int l = k + 1; l < sizeArray -1 && canWork == false; l++) {
for (int m = l + 1; m < sizeArray && canWork == false; m++) {
if (array[i] + array[k] + array[l] + array[m] == number) {
indices[0] = i;
indices[1] = k;
indices[2] = l;
indices[3] = m;
canWork = true;
}
}
}
}
}

sizeArray 后面的 - 2 和 -1以及以 + 1 开头的 - 用于跳过相同的总和。 我是一个非常初学者的程序员,所以如果代码那么糟糕,请原谅我。我也找不到有关此问题的任何内容,所以我在这里问。

正如我在对您的问题的评论中已经暗示的那样,解决此问题的最简单方法是使用所谓的动态规划。

这个想法是找到搜索n索引时的问题与搜索n + 1索引时的问题之间的关系。

在这种特殊情况下,我们可以使用以下观察结果将n + 1指数的情况减少为n指数的情况:

  • 有两种可能性:满足约束的n + 1索引的组合使用数组的最后一个索引,或者不使用。在第一种情况下,我们可以找到n + 1索引的组合,这些索引的总和为number通过在数组中搜索n索引,直到但排除总和为number - v的最后一个元素,其中v是数组中最后一个元素的值。如果我们找不到这样的组合(即我们在第二种情况下(,那么我们可以再次尝试在数组中搜索没有最后一个元素的n + 1索引。
  • 如果数组的元素少于n,则没有n索引的总和为number的组合。
  • n = 1的情况是微不足道的:我们只需要遍历数组一次,看看我们是否能找到一个等于我们正在寻找的数字的值。

这些观察结果的直接实现可能如下所示:

#include <algorithm>
#include <iterator>
#include <vector>
/**
* returns the `number_of_indices` indices of `input_array` for which 
* the corresponding elements sum to `sum`, or an empty vector if
* there is no such combination of indices.
*/
std::vector<std::int64_t> find_n_indices_that_sum_to(std::vector<int> input_array, 
int number_of_indices,
int sum)
{
if (number_of_indices == 1)
{
// the trivial case, just search for one element equal to `sum`.
auto const match = std::find(std::cbegin(input_array),
std::cend(input_array),
sum);
return match != std::cend(input_array) 
? std::vector<std::int64_t>{std::distance(std::cbegin(input_array), match)}
: std::vector<std::int64_t>{};
} else if (static_cast<std::size_t>(number_of_indices) > std::size(input_array)) {
// not enough elements to find the required number of indices
return std::vector<std::int64_t>{};
} else {
auto const last_index = std::size(input_array) - 1;
auto const value = input_array.back();
// reduce the size of the array by 1 - either we find
// `number_of_indices - 1` additional indices that sum to 
// `sum - value` or we're in case 2 described above and try 
// to find `number_of_indices` indices in the smaller array
input_array.pop_back();
auto indices = find_n_indices_that_sum_to(input_array,
number_of_indices - 1, 
sum - value);
if (!indices.empty()) {
// case 1 - there is a combination of indices whose corresponding
//          elements sum to `sum` with one of them being the
//          very last index of the array
indices.push_back(last_index);
return indices;                 
} else {
// case 2 - we try again in the smaller array
return find_n_indices_that_sum_to(input_array,
number_of_indices,
sum);
}
}
}

您也可以在魔杖盒上尝试此解决方案。

如果您愿意,也可以尝试提高此解决方案的性能,例如 通过将input_array向量参数替换为gsl::span以避免复制,或者使函数尾递归甚至完全命令式以避免大number_of_indices的堆栈溢出。