Из моих исследований, я понимаю, что это должно быть рекурсивным решением
Вовсе нет.
Обратите внимание, что если вы не используете рекурсию без необходимости, вы можете избежать определенных потенциальных проблем (уровни рекурсии и рост стека на уровень), и часто легче понять код.
Давайте посмотрим, что вы делаете. Если мы будем игнорировать отрицательные числа на данный момент, вы в основном генерируя следующую последовательность (при к = 2, п = 4):
0 0 0 0 0 1 0 0 0 2 0 0
0 0 0 1 0 1 0 1 0 2 0 1
0 0 0 2 0 1 0 2 0 2 0 2
0 0 1 0 0 1 1 0 0 2 1 0
0 0 1 1 0 1 1 1 0 2 1 1
0 0 1 2 0 1 1 2 0 2 1 2
0 0 2 0 0 1 2 0 0 2 2 0
0 0 2 1 0 1 2 1 0 2 2 1
0 0 2 2 0 1 2 2 0 2 2 2
Если к 9 были просто бы подсчет в десятичной системе счисления. Из всех детей, которых я видел, научиться считать, я никогда не знал, чтобы это делалось с помощью рекурсии. ;) Если вы отступите и подумайте о том, как вы научились считать большие числа, вы должны найти гораздо более простое решение ... Но я сохраню это позже.
Если считать в двоичной системе это будет выглядеть следующим образом:
0 = 000
1 = 001
2 = 010
3 = 011
4 = 100
5 = 101
6 = 110
7 = 111
Или подсчитывать с k=1
и n=3
(используя -k к):
0 = -1 -1 -1 9 = 0 -1 -1 18 = 1 -1 -1
1 = -1 -1 0 10 = 0 -1 0 19 = 1 -1 0
2 = -1 -1 1 11 = 0 -1 1 20 = 1 -1 1
3 = -1 0 -1 12 = 0 0 -1 21 = 1 0 -1
4 = -1 0 0 13 = 0 0 0 22 = 1 0 0
5 = -1 0 1 14 = 0 0 1 23 = 1 0 1
6 = -1 1 -1 15 = 0 1 -1 24 = 1 1 -1
7 = -1 1 0 16 = 0 1 0 25 = 1 1 0
8 = -1 1 1 17 = 0 1 1 26 = 1 1 1
Так что, если вы чувствуете вы можете:
- легко вычислить количество перестановок t о выходной
- использовать простой цикл для цикла через диапазон
- преобразовать каждое число в базовые к * 2 +-
- смещения каждой цифра вычитания K
Конечно, есть и более простой подход намекала раньше. Вызовите Counter(k, nest_level);
в коде ниже. (Объяснение после)
void WriteVector(const std::vector<int>& v)
{
for (const auto i : v)
std::cout << i << " ";
std::cout << std::endl;
}
bool VectorInc(const int k, std::vector<int>& v)
{
for (auto it = v.rbegin(); it != v.rend(); it++)
{
if ((*it) < k) {
(*it)++;
return true;
}
(*it) = -k;
}
return false;
}
void Counter(const int k, const int n)
{
std::vector<int> v(n, -k);
WriteVector(v);
while (VectorInc(k, v))
WriteVector(v);
}
Counter
инициализирует вектор с size == nest_level
и каждый элемент, содержащий -k
.
- В цикле он вызывает
VectorInc
, чтобы имитировать добавление 1 (или подсчет).
VectorInc
- очень простая функция, которая проходит через векторные элементы справа налево до тех пор, пока ей необходимо выполнить «перенос».
- Он обновляет текущий элемент путем добавления 1.
- Но если текущий элемент это при максимальной
k
, он должен пролонгировать обратно -k
, и «переброс» +1 к цифре слева.
- Когда вектор в конечном итоге достигает
{k, k, k, ..., k}
, добавляя 1 рулоны каждой цифру обратно -k
и VectorInc
возвращает ложные указывающих произошло переполнение.
Pros: Простой, без рекурсии, и будет работать с почти любыми значениями K & п.
Против: Будет работать практически с любыми значениями k & n. Попробуйте, казалось бы, безобидный вызов, например Counter(10, 80)
, и вы будете долго ждать, пока ваша программа будет считать атомы во вселенной.
Вы попробовали [обсудить это с вашей резиновой утиной] (https://en.wikipedia.org/wiki/Rubber_duck_debugging)? –