Problem
Given two non-negative integers, find the greatest common divisor (GCD) along with the coefficients of Bézout’s identity (x and y such that ax + by = gcd(a, b)
) using the Extended Euclidean algorithm with the modulo operator.
Examples
Example 1:
Input: 56, 98
Output: (14, -1, 1)
Explanation:
GCD is 14 with coefficients x = -1 and y = 1 for the equation 56(-1) + 98(1) = 14
Example 2:
Input: 48, 18
Output: (6, 1, -2)
Explanation:
GCD is 6 with coefficients x = 1 and y = -2 for the equation 48(1) + 18(-2) = 6
Solution
The Extended Euclidean Algorithm extends the basic Euclidean algorithm to find not just the GCD but also the coefficients (x and y) for Bézout’s identity.
Here is the approach:
- Implement the basic Euclidean algorithm using the modulo operator. We have covered it here Basic Euclidean Algorithm to find GCD of two numbers using modulo operator.
- Track the coefficients x and y using recursion to build the solution for Bézout’s identity.
Method 1 - Recursive
The extended Euclidean algorithm refines the results of gcd(a, b)
by employing the results from the recursive call gcd(b % a, a)
. If x1
and y1
are derived from this recursive call, then x
and y
are updated as follows:
x = y1 - ⌊b/a⌋ * x1
y = x1
Code
Java
public class ExtendedEuclideanGCD {
public static class Result {
int gcd, x, y;
public Result(int gcd, int x, int y) {
this.gcd = gcd;
this.x = x;
this.y = y;
}
@Override
public String toString() {
return "GCD: " + gcd + ", x: " + x + ", y: " + y;
}
}
public Result extendedGCD(int a, int b) {
if (a == 0) {
return new Result(b, 0, 1);
}
Result result = extendedGCD(b % a, a);
int x = result.y - (b / a) * result.x;
int y = result.x;
return new Result(result.gcd, x, y);
}
public static void main(String[] args) {
ExtendedEuclideanGCD solution = new ExtendedEuclideanGCD();
System.out.println(solution.extendedGCD(56, 98)); // Output: GCD: 14, x: -1, y: 1
System.out.println(solution.extendedGCD(48, 18)); // Output: GCD: 6, x: 1, y: -2
}
}
Python
class ExtendedEuclideanGCD:
class Result:
def __init__(self, gcd, x, y):
self.gcd = gcd
self.x = x
self.y = y
def __repr__(self):
return f"GCD: {self.gcd}, x: {self.x}, y: {self.y}"
def extended_gcd(self, a, b):
if a == 0:
return self.Result(b, 0, 1)
result = self.extended_gcd(b % a, a)
x = result.y - (b // a) * result.x
y = result.x
return self.Result(result.gcd, x, y)
# Example usage
eg = ExtendedEuclideanGCD()
print(eg.extended_gcd(56, 98)) # Output: GCD: 14, x: -1, y: 1
print(eg.extended_gcd(48, 18)) # Output: GCD: 6, x: 1, y: -2
Complexity
- ⏰ Time complexity:
O(log(min(a, b)))
- 🧺 Space complexity:
O(log(min(a, b))
due to the recursive stack.
How is extended algorithm useful?
The extended Euclidean algorithm is highly effective when a
and b
are coprime, i.e., their gcd is 1. In this algorithm, x
serves as the modular multiplicative inverse of a modulo b
, and y
is the modular multiplicative inverse of b modulo a
. Calculating the modular multiplicative inverse is a crucial part of the RSA public-key encryption process.