2013-03-26 9 views
-3

jI Есть ли способ создать рекурсивную функцию следующего кода?Рекурсия для вложенных циклов

for(int i=0; i<1000000; i++){ 
    for(int j=0; j<1000000; j++){ 
     for(int k=0; k<1000000; k++){ 
      //Do something using i,j and k 
     } 
    } 
} 

Мне нужно, чтобы он сочетал все возможные последовательности чисел. например: (0,0,0) (0,0,1) (0,1,0)

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

Благодаря

+1

Есть ли способ? Конечно. Я вижу причину? Нет. Не могли бы вы уточнить, почему рекурсия была бы лучше, чем итерация в этом случае? – Makoto

+0

Если я не ошибаюсь, все, что можно сделать с помощью итерации, можно сделать с помощью рекурсии, вам просто нужно подумать о способе ее достижения. – Abubakkar

+1

Кроме того, вы используете «i» в завершении цикла «j». Просто говорю. – pandorym

ответ

3

В теории, каждый итерационный цикл может быть преобразован в рекурсивный вызов (либо с бесконечным стеком или через tail-call), однако:

  1. Рекурсия не быстрее чем итерации - сложность времени идентична
  2. Java не поддерживает TCO и, таким образом, не поддерживает такие глубокие рекурсивные звонки - десятки десятков: да, миллионы: абсолютно нет

В этом случае это занимает много времени, потому что оно пеет смешное количество раз. Алгоритмом грубой силы является O (n c), где c равно 3, то есть the bounds are polynomial time (это не хорошо), а n является «относительно большим». Это многоwasted CPU cycles.

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

+0

@ Dukeling 1. [Константы учтены] (http://en.wikipedia.org/wiki/Big_O_notation) (время «настенных часов» может отличаться для определенного n) 2. Конечно, можно записаться только одно измерение. – 2013-03-26 09:07:07

+0

О, ну, сложность. Обновленный комментарий - 1) Сложность времени может быть одинаковой, но в Java рекурсия обычно медленнее ([this] (http://stackoverflow.com/a/2651200/1711796) вкратце упоминает об этом), хотя только небольшим постоянный множитель, но, учитывая простоту данного кода, он может значительно изменить разницу. 2) То, как я думаю, требует только глубины рекурсии 3, а не миллионов. Не знаете, как еще вы хотите это сделать. – Dukeling

0

Рассмотрите следующее, рекурсия, пройдите это подробно. Is recursion ever faster than looping?

Так как вы отметили Java, рекурсия стоит дороже итерации, поскольку память стека должна выделяться. Итак, если вы намерены записать эту перестановку, тогда лучше сохранить их в файл для последующего использования. И это зависит от вашего заявления о проблеме, для которого можно указать более точный ответ.

0

Почему преобразования, что рекурсивный, что собирается сделать его работать медленнее ..

Но вы можете попробовать это:

public static void recursiveLoop (int i, int j, int k, int w, int h, int d) 
{ 

    /* code .. */ 

    /* increment i,j,k */ 
    if (k == d) 
    { 
     k = 0; 
     j++; 
    } 

    if (j == h) 
    { 
     j = 0; 
     i++; 
    } 

    if (i == w) 
    { 
     return; // Stop 
    } 

    recursiveLoop(i,j,k); 

} 

Но компилятор изменит его во что-то вроде этого:

public static void recursiveLoop (int i, int j, int k, int w, int h, int d) 
{ 

    do 
    { 

     /* code .. */ 

     /* increment i,j,k */ 
     if (k == d) 
     { 
      k = 0; 
      j++; 
     } 

     if (j == h) 
     { 
      j = 0; 
      i++; 
     } 

    }while (i != w); 

} 
+2

'' компилятор изменит его на это ", - я в этом сильно сомневаюсь. Они могут функционировать одинаково, но компилятор не будет преобразовывать рекурсивную функцию в итеративную (по крайней мере, это не будет в Java). – Dukeling

+0

@ Dukeling Вы правы, я не уверен в большинстве из них, но я знаю, что преобразование хвостовой рекурсии в цикл while является общей синтаксической оптимизацией компилятора, что маловероятно, так это оптимизация хвостовой рекурсии по модулю –

+2

Обратите внимание, что Java/JVM не поддерживает оптимизацию хвостового вызова. [Релевантные] (http://stackoverflow.com/questions/105834/does-the-jvm-prevent-tail-call-optimizations). Также обратите внимание, что, поскольку проверка завершена, вероятно, будет 'do {...} while();', а не 'while() {...}'. – Dukeling

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