2016-03-03 2 views
1

Я уверен, что полностью понимаю, как работают методы только с одной рекурсией.Двойная рекурсия одним способом Java

Ex) вычисление факториала

public int factorial(int n){ //factorial recursion 
    if(n==0){ 
     return 1; 
    } 
    else{ 
     return n*factorial(n-1); 
    } 
} 

Для этих методов, я могу даже представить себе, что происходит в штабеля и какие значения возвращаются на каждом уровне стека.

Но когда я сталкиваюсь с методами с Двойными рекурсиями, начинается кошмар.

Ниже приведена проблема рекурсии с двойными рекурсиями от кодирующей биты.

Ex) Учитывая массив значений ints, можно ли выбрать группу некоторых из int, чтобы группа суммировалась с заданной целью? Если да, то верно. Если нет, false. Вы используете 3 параметра; начальный индекс начало, An int Array nums, target int value target.

Ниже приведено решение этой проблемы.

public boolean groupSum(int start, int[] nums, int target) { 
    if (start >= nums.length) return (target == 0); 
    if (groupSum(start + 1, nums, target - nums[start])) return true; 
    if (groupSum(start + 1, nums, target)) return true; 
    return false; 
} 

Мое желание понять это решение. Скажем, мне был присвоен массив {2,4,8} с начальным индексом = 0 и целевым значением 10. Таким образом, (0, {2,4,8}, 10) проходит через метод, функция возвращается -called на

if (groupSum(start + 1, nums, target - nums[start])) return true; 

поэтому она становится (1,{2,4,8},8) и он делает снова и снова, пока индекс не достигнет начала
. когда он достигает 3. Стек на последнем уровне (?) переходит ко второму рекурсивному вызову. И здесь я начинаю терять следы происходящего.

Может ли кто-нибудь сломать это для меня? И когда люди используют двойную рекурсию (я знаю, что она очень неэффективна и на практике почти никто не использует ее для своей неэффективности, а просто пытается понять ее). Может ли они на самом деле визуализировать, что произойдет? или они просто используют его, надеясь, что базовый регистр и рекурсия будут работать правильно? Я думаю, что это относится вообще ко всем госзакупках, писавших сортировки слиянием, башни Ханоя alogrithm и т.д ..

Любая помощь очень ценится ..

+4

Вы здесь придумываете терминологию. Это не «двойная рекурсия» - то, что вы показали, является обычной рекурсией. Кроме того, как однажды сказал мудрый человек: «Чтобы понять рекурсию, вы должны сначала понять рекурсию». – vaxquis

+0

ну, наверное, я не понял рекурсии. Поэтому, пожалуйста, просветите меня. – Hello

+1

быть моим гостем: http: // stackoverflow.com/questions/3021/what-is-recursion-and-when-should-i-use-it https://en.wikipedia.org/wiki/Recursion http://stackoverflow.com/questions/126756/examples- рекурсивных функций – vaxquis

ответ

2

Идея двойной рекурсии состоит в том, чтобы разбить проблему на две более мелкие проблемы. Как только вы решаете меньшие проблемы, вы можете либо присоединиться к их решениям (как это делается в сортировке слияния), либо выбрать один из них - что сделано в вашем примере, что требует только второй более мелкой проблемы, которая будет решена при решении первой более мелкой проблемы не решила полную проблему.

Ваш пример пытается определить, существует ли подмножество входного массива nums, сумма которого равна сумме target.start определяет, какая часть массива рассматривается текущим рекурсивным вызовом (когда оно равно 0, рассматривается весь массив).

Проблема сломана до двух, поскольку, если такое подмножество существует, оно либо содержит первый элемент массива (в этом случае проблема сводится к поиску, существует ли подмножество последних элементов n-1 из массива, сумма которого равна target минус значение первого элемента) или не содержит его (в этом случае проблема сводится к поиску, существует ли подмножество последних n-1 элементов массива, сумма которых равна target).

Первая рекурсия обрабатывает случай, когда подмножество содержит первый элемент, поэтому он делает рекурсивный вызов, который будет искать целевую сумму минус первый элемент в остальных n-1 элементах массива. Если первая рекурсия возвращает true, это означает, что существует требуемое подмножество, поэтому вторая рекурсия никогда не вызывается.

Вторая рекурсия обрабатывает случай, когда подмножество не содержит первый элемент, поэтому он делает рекурсивный вызов, который будет искать целевую сумму в остальных n-1 элементах массива (на этот раз первый элемент не вычитается из целевой суммы, так как первый элемент не включается в сумму). Опять же, если второй рекурсивный вызов возвращает true, это означает, что существует необходимое подмножество.

+0

Я думаю, что функция может иметь 1 улучшение - она ​​может проверять 'target == 0' в первой строке и' return true' сразу же после того, как мы уже достигли цели - в настоящее время она излишне петли через весь массив. Как вы думаете? – radoh

+0

Благодарим за ответ. Но не могли бы вы объяснить, почему он был разделен на два с первым элементом или без него? почему другие элементы не считались? – Hello

+0

@LookAtTheBigPicture Существует множество способов разбить проблему на более мелкие части. Вы можете рассмотреть первые два элемента, и тогда проблема будет разбита на четыре части (в зависимости от того, будут ли оба, ни один или один из первых двух элементов в подмножестве, имеющем целевую сумму). Это сделает код более сложным. – Eran

1

Пытаться понять это следующим образом: Рекурсия может быть переписано как некоторое время -loop. где условие while является отрицанием стоп-условия рекурсии.

Как уже говорилось, нет ничего двойного рекурсии.

1

Ну, если вы хотите визуализировать его, обычно это похоже на дерево. Вы сначала следуете по одному пути через дерево до конца, затем выполняете один шаг назад и выбираете другой путь (если это возможно). Если их нет или вы довольны своим результатом, вы просто делаете еще один шаг назад и так далее.

Я не знаю, поможет ли это вам, но когда я узнал рекурсию, это помогло мне просто подумать о моем методе, который уже работает. Итак, я подумал: «Отлично, поэтому в основном мой метод уже работает, но я не могу назвать его с теми же параметрами и должен удостовериться, что возвращаю правильное значение для этих точных параметров, используя разные.

Если мы возьмем этот пример: Сначала мы знаем, что если у нас нет номера, чтобы смотреть слева, то ответ зависит от того, если цель 0. (первая линия)

Теперь то, что мы делаем с остальными? Ну ... нам нужно подумать об этом на мгновение. Просто подумайте о самом первом номере. При каких обстоятельствах это часть решения? Хорошо, если бы вы могли создать номер цели-firstnumber с остальными числами. Потому что тогда, когда вы добавляете firstnumber, вы достигаете цели. Итак, вы пытаетесь понять, возможно ли это. Если это так, то оно разрешимо. (вторая строка)

Но если нет, все же возможно, что первое число просто не важно для решения. Поэтому вам нужно попытаться снова создать цель без этого числа. (третья строка)

И это в основном все, что есть.

Конечно, для этого нужно две вещи: 1. Вам нужно верить, что ваш метод уже работает для других параметров. 2. Вам нужно убедиться, что ваша рекурсия завершена. Это первая строка в этом примере, но вы всегда должны думать о том, есть ли какая-либо комбинация параметров, которая просто создаст бесконечную рекурсию.

Смежные вопросы