【问题标题】:Find all combinations for x^n and check if they add up to a number excluding same numbers查找 x^n 的所有组合,并检查它们加起来是否等于一个数字,不包括相同的数字
【发布时间】:2018-09-15 15:15:52
【问题描述】:

所以我正在寻找一个程序,它遍历数组索引的所有组合,并检查数组中是否有对应的数字加起来为特定数字(例如,有 2 个索引:array[0 to 10] +数组[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 的开头用于跳过相同的总和。 我是一个非常初学者的程序员,所以如果代码那么糟糕,请原谅我。我也找不到关于这个问题的任何信息,所以我在这里问。

【问题讨论】:

  • 你应该看看dynamic programming
  • "查找 x^n ... 的所有组合" - 注意在 C++ 中 ^ 表示 XOR,not 取幂。小心清楚地表达你想要什么,否则可能会被误解。

标签: c++ combinations


【解决方案1】:

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

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

在这种特殊情况下,我们可以通过以下观察将n + 1 索引的情况简化为n 索引的情况:

  • 有两种可能性:满足约束的n + 1 索引组合使用数组的最后一个索引,或者不使用。在第一种情况下,我们可以通过在数组中搜索 n 索引来找到总和为 numbern + 1 索引的组合,直到但不包括总和为 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);
        }
    }
}

您也可以在wandbox 上尝试此解决方案。

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

【讨论】:

    猜你喜欢
    • 2011-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-15
    • 2021-05-16
    • 2013-01-27
    • 2023-01-23
    相关资源
    最近更新 更多