Ваше решение основано на идее, что лучше идти назад, то есть от (c, d) к (a, b).Это потому, что когда вы начинаете с (a, b) и идете вперед, у вас есть две возможности для следующей пары, в то время как когда вы начинаете с (c, d) и идете назад, у вас, очевидно, есть только одна возможность - вам необходимо вычестьнаименьшее значение из наибольшего.
Это действительно верно для случая, когда оба значения a
и b
являются положительными.В этом случае, a+b>a
и a+b>b
, и, следовательно, по паре (c,d)
легко определить, какой шаг в цепочке преобразований был последним (это зависит от того, c>d
или d>c
).Однако это рассуждение нарушается, если a
или b
может быть отрицательным, так как в этом случае вы не знаете, следует ли вычитать c
из d
или наоборот.Это фундаментальная проблема в вашем подходе, и я не вижу простых способов ее преодоления.
Если мы рассмотрим только случай положительных a
и b
, то мы можем изменить ваше решение наболее эффективный.
Рассмотрим случай, когда c
намного больше, чем d
.В этом случае вы будете вычитать d
из c
много раз, вплоть до того момента, когда новый c
станет меньше d
.К чему вы прибудете в конце?Очевидно, что (c%d, d)
.Таким образом, вы можете сделать это за один шаг, придя к коду, очень похожему на евклидов алгоритм для наибольшего общего делителя.
Однако при таком переходе от вычитания к делению по модулю вы, возможно, фактически пропустили необходимую пару (т. Е. (A, b)).Однако это легко исправить, поскольку одно из чисел не изменяется, поэтому мы легко можем определить такую ситуацию.
Код будет выглядеть примерно так (не проверено)
while (c > 0 && d > 0) { // similar to how Eucledian algorithm is written
if (c > d) {
int new_c = c % d;
if (b == d) { // we should have seen (a,b) here
return (a % d == new_c && a >= new_c && a <= c);
}
c = new_c;
} else {
// a symmetrical case follows
...
}
}
Этот код имеет временную сложность O(log(c + d))
, в то время как ваш код с вычитаниями работает в O(c+d)
.
Что касается случая, когда a
и / или b
могут быть отрицательными, этокажется, гораздо более сложная проблема.