Encontrando o melhor divisor comum em Java
1. Visão geral
Em matemática, oGCD de dois inteiros, que não são zero, éthe largest positive integer that divides each of the integers evenly.
Neste tutorial, veremos três abordagens para encontrar o maior divisor comum (GCD) de dois inteiros. Além disso, veremos sua implementação em Java.
2. Força Bruta
Para nossa primeira abordagem, iteramos de 1 ao menor número fornecido e verificamos se os números inteiros são divisíveis pelo índice. The largest index which divides the given numbers é o GCD dos números fornecidos:
int gcdByBruteForce(int n1, int n2) {
int gcd = 1;
for (int i = 1; i <= n1 && i <= n2; i++) {
if (n1 % i == 0 && n2 % i == 0) {
gcd = i;
}
}
return gcd;
}
Como podemos ver, a complexidade da implementação acima éO(min(n1, n2)) porque precisamos iterar no loop porn vezes (equivalente ao número menor) para encontrar o GCD.
3. Algoritmo de Euclides
Em segundo lugar, podemos usar o algoritmo de Euclides para encontrar o GCD. O algoritmo de Euclid não é apenas eficiente, mas também fácil de entender e implementar usando recursão em Java.
O método de Euclides depende de dois teoremas importantes:
-
Primeiro, se subtrairmos o número menor do número maior, o GCD não muda -therefore, if we keep on subtracting the number we finally end up with their GCD
-
Segundo, quando o número menor divide exatamente o número maior, o número menor é o MDC dos dois números fornecidos.
Observe em nossa implementação que usaremos módulo em vez de subtração, pois são basicamente muitas subtrações por vez:
int gcdByEuclidsAlgorithm(int n1, int n2) {
if (n2 == 0) {
return n1;
}
return gcdByEuclidsAlgorithm(n2, n1 % n2);
}
Além disso, observe como usamosn2 na posição den1 e usamos o restante na posição de n2 na etapa recursiva do algoritmo.
Além disso,the complexity of Euclid’s algorithm is O(Log min(n1, n2)) which is better as compared to the Brute Force method we saw before.
4. Algoritmo de Stein ou Algoritmo Binário GCD
Finalmente, podemos usar o algoritmo de Stein, tambémknown as the Binary GCD algorithm, para encontrar o GCD de dois inteiros não negativos. Esse algoritmo usa operações aritméticas simples, como mudanças aritméticas, comparação e subtração.
O algoritmo de Stein aplica repetidamente as seguintes identidades básicas relacionadas a GCDs para encontrar GCD de dois inteiros não negativos:
-
gcd (0, 0) = 0, gcd (n1, 0) = n1, gcd (0, n2) = n2
-
Quandon1 en2 são ambos inteiros pares, entãogcd(n1, n2) = 2 * gcd(n1/2, n2/2), uma vez que 2 é o divisor comum
-
Sen1 for inteiro par en2 for inteiro ímpar, entãogcd(n1, n2) = gcd(n1/2, n2), uma vez que 2 não é o divisor comum e vice-versa
-
Sen1 en2 são ambos números inteiros ímpares en1 >= n2, entãogcd(n1, n2) = gcd((n1-n2)/2, n2) e vice-versa
Repetimos os passos 2-4 até quen1 seja igual an2 oun1 = 0. O GCD é(2n) * n2. Aqui,n é o número de vezes que 2 é comum emn1en2 durante a execução da etapa 2:
int gcdBySteinsAlgorithm(int n1, int n2) {
if (n1 == 0) {
return n2;
}
if (n2 == 0) {
return n1;
}
int n;
for (n = 0; ((n1 | n2) & 1) == 0; n++) {
n1 >>= 1;
n2 >>= 1;
}
while ((n1 & 1) == 0) {
n1 >>= 1;
}
do {
while ((n2 & 1) == 0) {
n2 >>= 1;
}
if (n1 > n2) {
int temp = n1;
n1 = n2;
n2 = temp;
}
n2 = (n2 - n1);
} while (n2 != 0);
return n1 << n;
}
Podemos ver que usamos operações de deslocamento aritmético para dividir ou multiplicar por 2. Além disso, usamos subtração para reduzir os números fornecidos.
A complexidade do algoritmo de Stein quandon1 > n2 éO((log2n1)2) enquanto. quandon1 < n2, éO((log2n2)2).
5. Conclusão
Neste tutorial, analisamos vários métodos para calcular o MDC de dois números. Também os implementamos em Java e analisamos rapidamente sua complexidade.
Como sempre, o código-fonte completo de nossos exemplos aqui é, como sempre,over on GitHub.