Стараюсь понять как работает рекурсия. Вот пример как перемножить два числа с помощью цикла:
public int mult(int a, int b){
int sum=0;
for (int i=0;i<b;i++){
sum+=a;
}
return sum;
}
Пожалуйста подскажите, как переделать этот цикл с помощью рекурсии ? (используя только сложение)
Решение в лоб достаточно тривиальное, но даже здесь надо учитывать наличие граблей:
private int mult_step(int summand, int steps_count){
if (steps_count > 0)
return summand + mult(summand, steps_count - 1);
else
return 0;
}
public int mult(int a, int b){
int summand, steps_count;
Boolean negate;
if(a > b){
summand = a;
steps_count = Math.abs(b);
negate = (b < 0);
} else{
summand = b;
steps_count = Math.abs(a);
negate = (a < 0);
}
int sum = mult_step(summand, steps_count);
return negate ? -sum : sum;
}
То есть сначала мы спускаемся вглубь по цепочке из b элементов, после чего начинаем подниматься обратно, накапливая сумму.
Поясню, о каких граблях шла речь:
Множители могут быть отрицательными. Если это не учесть, то будет бесконечная рекурсия.
При больших b цепочка получится длиннее, чем может вместить в себя стек. Поэтому в качестве длины цепочки надо брать наименьший из множителей.
function int mult(int a, int b){
int sum = a;
if(b>1){
sum += mult(a,b-1);
}
return sum;
}
Могу ошибаться. Не знаю зачем вообще нужны эти задачки на рекурсию. Ее нужно по возможности избегать
Можно по аналогии с алгоритмом быстрого возведения в степень:
public static int mul(int a, int b){
if (b < 0) return -mul(a, -b); // обработка отрицательных значений
if (b == 1) return a; // тривиальные условия выхода
if ((b & 1) == 1) return a + mul(a, b-1); // обработка нечётных
return mul(a, b >> 1) << 1; // логарифмический спуск на чётных
}
Рабочее демо на js:
function mul(a, b) {
if (b < 0) return -mul(a, -b);
if (b == 1) return a;
if ((b&1) == 1) return a + mul(a, b-1);
return mul(a, b >> 1) << 1;
// за счёт деления на 2 мы получаем всего logN итераций
}
[
[2, 7],
[3, 8],
[-13, -17],
].forEach(([a, b]) => console.log(
a, b,
mul(a, b),
mul(a, b) === a*b
));
Можно еще так:
int mult(int min, int max) {
if (min == max) {
return max;
}
return mult(++min, max);
}
Но все зависит от того, что за операции нужно делать.
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Имеется класс WorkoutDetailFragment который наследуется от FragmentПри попытке замены этого фрагмента выводится ошибка
Хочу научиться использовать Spring Data без Spring Boot