StackOverflowError при поиске взаимно простых пар для 2 чисел с использованием рекурсивной функции. Можем ли мы преобразовать ее в итерацию

Я хотел рассчитать количество пар (m,n), где GCD(m,n)=x, скажем, x=1 и 1‹=m‹=M=10^5 и 1‹=n‹=N=10^ 5.

M и N будут даны

Примечание. Мне просто нужно количество возможных пар, а не пар.

ОГРАНИЧЕНИЕ ПО ВРЕМЕНИ: 5 сек.

Приведенный ниже код хорошо работает для небольших чисел, но для больших выдает StackOverflowError.

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.math.BigInteger;

public class TestClass{
static long M;
static long N;
static long totalCount = 1;

public static void main(String[] args) throws Exception{
    M = 100000;
    N = 2000;
    findCoPrimes(2, 1);
    findCoPrimes(3, 1);
    System.out.println(totalCount);
}

public static void findCoPrimes(int m, int n){
    if ((n > N) || (m > M)){
        return;
    }
    if (n != m && m <= N){
        totalCount++;
    }
    totalCount++;
    findCoPrimes(2*m - n, m);
    findCoPrimes(2*m + n, m);
    findCoPrimes(m + 2*n, n);
}
}

Может ли кто-нибудь помочь мне преобразовать эту рекурсивную функцию в итеративную функцию, чтобы избежать ошибки StackOverflow.

Пожалуйста, помогите мне найти решение для этого. Любые другие лучшие подходы также будут рассмотрены. В этом вопросе есть подсказка: используйте умные способы найти простые множители, а затем найдите количество взаимно простых пар. Грубая сила не сработает.


person Ajinkya Mahagaonkar    schedule 28.05.2014    source источник
comment
Вся рекурсия может быть развернута с помощью структуры данных стека... рекурсия - это просто способ использования встроенного стека компьютера вместо вашего собственного   -  person Matt Coubrough    schedule 28.05.2014
comment
Не могли бы вы привести результаты, например, для M=9, N=4? Ваша программа говорит, что ответ равен 25, но когда я перечисляю их вручную, я получаю 19: {(1,2), (1,3), (1,4), (1,5), (1,6) , (1,7), (1,8), (1,9), (2,3), (2,5), (2,7), (2,9), (3,4), ( 3,5), (3,7), (3,8), (4,5), (4,7), (4,9)}. Что я упускаю/не понимаю?   -  person pjs    schedule 28.05.2014
comment
@pjs вы пропустили (2,1)(3,1)(3,2)(4,1)(4,2)(4,3) Итак, теперь вам 25 :). Не могли бы вы помочь. Я мог бы преобразовать приведенный выше код в итеративный. Но не работает хорошо с более высокими числами! :(   -  person Ajinkya Mahagaonkar    schedule 29.05.2014
comment
Есть лучший подход. Подсказка, которую я получил, заключалась в следующем: используйте умные способы, чтобы найти простые множители, а затем найти количество взаимно простых пар. Грубая сила не сработает. Но нет возможного решения :(   -  person Ajinkya Mahagaonkar    schedule 29.05.2014
comment
Так порядок имеет значение? Это меня удивляет. Это прямое слово от вашего инструктора?   -  person pjs    schedule 29.05.2014
comment
Да, этот намек прямо от инструктора!   -  person Ajinkya Mahagaonkar    schedule 30.05.2014


Ответы (1)


Чтобы преобразовать в итеративную функцию, вы можете создать объект стека, который вы используете для имитации стека функций.

Использование объекта стека позволит вам хранить свое состояние в куче вместо стека, который по умолчанию обычно установлено значение 256 КБ.

См. общий подход к преобразованию в итерацию здесь: https://stackoverflow.com/a/159777/276949

person Martin Konecny    schedule 28.05.2014
comment
так что вместо переполнения стека он в итоге получит переполнение кучи Java :) Не думаю, что это решит проблему. - person Oleg Gryb; 28.05.2014
comment
Почему нет? Куча способна хранить гораздо больше, чем стек - person Martin Konecny; 28.05.2014
comment
Вы можете увеличить размер стека так же, как вы можете увеличить кучу. - person Oleg Gryb; 28.05.2014
comment
@Oleg Gryb Вам не нужно увеличивать размер кучи (по умолчанию он больше, чем стек), и, используя собственную структуру данных стека вместо стека JVM, вы можете управлять и отслеживать состояние вашего стека - это дает вы гораздо лучше контролируете, чем полагаетесь на рекурсию. - person Matt Coubrough; 28.05.2014
comment
Неважно, что больше по умолчанию, если вы можете легко изменить максимальный размер. Управление и мониторинг не сильно помогут, если у вас заканчивается память. В любом случае удачи в конвертации. - person Oleg Gryb; 28.05.2014
comment
Размер стека по умолчанию составляет около 128 КБ в зависимости от платформы, в то время как куча по умолчанию составляет не менее 8 МБ, поэтому мы говорим о гораздо большем количестве памяти для игры. - person Matt Coubrough; 28.05.2014