Как я уже намекал в своем комментарии к вашему вопросу, самый простой способ решить эту проблему - использовать так называемое динамическое программирование .
Идея состоит в том, чтобы найтисвязь между проблемой при поиске n
индексов и проблемой при поиске n + 1
индексов.
В данном конкретном случае мы можем свести регистр n + 1
к случаю n
индексы с использованием следующих наблюдений:
- Есть две возможности: либо комбинация
n + 1
индексов, которая удовлетворяет ограничениям, использует самый последний индекс массива, либо нет.В первом случае мы можем найти комбинацию n + 1
индексов, которые суммируются с number
, путем поиска n
индексов в массиве вплоть до, но исключая последний элемент, который суммируется с number - v
, где v
является значениемпоследнего элемента в массиве.Если мы не можем найти такую комбинацию (т. Е. Мы находимся во втором случае), то мы можем снова попытаться найти индексы n + 1
в массиве без последнего элемента. - Не существует комбинации
n
указывает, что сумма равна number
, если массив содержит менее n
элементов. - Случай
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
.