Problem Statement
You are given two integers n1 and n2. You need find the Greatest Common Divisor (GCD) of the two given numbers. Return the GCD of the two numbers.
The Greatest Common Divisor (GCD) of two integers is the largest positive integer that divides both of the integers.
Examples
Example 1:
Input: n1 = 4, n2 = 6
Output: 2
Explanation:
Divisors of n1 = 1, 2, 4
Divisors of n2 = 1, 2, 3, 6
Greatest Common Divisor = 2
Example 2:
Input: n1 = 7, n2 = 3
Output: 1
Explanation:
Divisors of n1 = 1, 7
Divisors of n2 = 1, 3
Greatest Common Divisor = 1
Approaches
1️⃣ Brute Force Approach
Intuition:
The GCD (Greatest Common Divisor), also known as HCF (Highest Common Factor), of two numbers is the largest number that divides both without leaving a remainder. To find the GCD, check all numbers from 1 up to the smaller of the two input numbers for common factors. The largest of these common factors is the GCD.
Approach:
- Initialize a variable gcd with 1 that will store the greatest common divisor of the two given numbers.
- Iterate from 1 to the minimum of the two numbers using a loop variable. Update the gcd if both the given numbers are divisible by the current value of the loop variable.
- After the iterations are over, the greatest common divisor will be stored in the gcd variable.
Dry Run:
Initialization:
N1 = 4
N2 = 6
gcd = 1
First Iteration:
i = 1
N1 % i == 0 && N2 % i == 0
4 % 1 == 0 && 6 % 1 == 0
True
gcd = 1 (unchanged)
Second Iteration:
i = 2
N1 % i == 0 && N2 % i == 0
4 % 2 == 0 && 6 % 2 == 0
True
gcd = 2 (changed)
Third Iteration:
i = 3
N1 % i == 0 && N2 % i == 0
4 % 3 == 0 && 6 % 2 == 0
1 == 0 && 0 == 0
False
gcd = 2 (unchanged)
Fourth Pass:
i = 4
N1 % i == 0 && N2 % i == 0
4 % 4 == 0 && 6 % 4 == 0
0 == 0 && 0 == 2
False
gcd = 2 (unchanged)
Loop Termination:
i has become 5 which is larger than minimum of (4, 6)
So, Loop Terminated,
i = 5 > min(4, 6)
gcd = 2
return gcd
Code:
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
/* Function to find the
GCD of two numbers */
int GCD(int n1, int n2) {
// Variable to store the gcd
int gcd = 1;
// Iterate from 1 to min(n1, n2)
for(int i = 1; i <= min(n1, n2); i++) {
/* Check if i is a common
divisor of both n1 and n2 */
if(n1 % i == 0 && n2 % i == 0) {
// Update gcd
gcd = i;
}
}
// Return stored GCD.
return gcd;
}
};
int main() {
int n1 = 4, n2 = 6;
/* Creating an instance of
Solution class */
Solution sol;
/* Function call to find the
gcd of two numbers */
int ans = sol.GCD(n1, n2);
cout << "GCD of " << n1 << " and " << n2 << " is: " << ans << endl;
return 0;
}
Complexity Analysis:
- Time Complexity:
O(min(N1, N2))
– where N1 and N2 are given numbers. Iterating from 1 to min(N1, N2) and performing constant time operations in each iteration. - Space Complexity:
O(1)
– Using a couple of variables i.e., constant space.
2️⃣ Backward Loop
Intuition:
The time complexity of the previous approach can be optimized if we iterate backward from min(n1, n2) to 1. This way the first divisor that is found for both numbers can be returned as the greatest common divisor of the numbers saving unnecessary iterations.
Approach:
- Declare a variable gcd that will store the greatest common divisor of the two given numbers.
- Iterate from the minimum of the two numbers down to 1 using a loop variable. Update the gcd if both the given numbers are divisible by the current value of the loop variable and break out from the loop to save unnecessary iterations.
- The greatest common divisor for the two numbers is stored in the gcd variable which can be returned as the answer.
Dry Run:
Initially:
Initially
N1 = 4
N2 = 6
gcd = 1
First Iteration:
i = 4 (miniumum of N1 and N2)
N1 % i == 0 && N2 % i == 0
4 % 4 == 0 && 6 % 4 == 0
False
gcd = 1, Unchanged
Decrement i by 1
Second Iteration:
i = 3
N1 % i == 0 && N2 % i == 0
4 % 3 == 0 && 6 % 3 == 0
False
gcd = 1, Unchanged
Decrement i by 1
Third Iteration:
i = 2
N1 % i == 0 && N2 % i == 0
4 % 2 == 0 && 6 % 2 == 0
True
gcd = 2
Terminate the loop here and return the gcd
Code:
int GCD(int n1, int n2) {
// Variable to store the gcd
int gcd;
// Iterate from 1 to min(n1, n2)
for(int i = min(n1, n2); i >= 1; --i) {
/* Check if i is a common
divisor of both n1 and n2 */
if(n1 % i == 0 && n2 % i == 0) {
// Update gcd
gcd = i;
// Break to skip unnecessary iterations
break;
}
}
// Return stored GCD.
return gcd;
}
Complexity Analysis:
- Time Complexity:
O(min(N1, N2))
– where N1 and N2 are given numbers. In the worst case, finding GCD will require iterating from min(N1, N2) till 1 and performing constant time operations in each iteration. - Space Complexity:
O(1)
– Using a couple of variables i.e., constant space.
3️⃣ Optimal Approach
Intuition:
We can make use of the Euclid's Algorithm
.
Euclid's Algorithm:
The algorithm is based on the principle that the GCD of two numbers a
and b
is the same as the GCD of b
and a % b
. We keep reducing the problem size by replacing a
with b
and b
with a % b
until b
becomes 0. At this point, a
will be the GCD.
Formula:
gcd(a, b) = gcd(b, a % b)
When b = 0
, a
is the GCD.
Approach:
- Initialize a while loop till both numbers are greater than zero.
- In each iteration perform the modulus operation of the greater number with the smaller number.
- Once the loop terminates, one of the two variables stores a non-zero value which is the GCD for the given pair of numbers.
Code:
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
/* Function to find the
GCD of two numbers*/
int GCD(int n1, int n2) {
/* Continue loop as long as both
n1 and n2 are greater than zero */
while(n1 > 0 && n2 > 0) {
/* If n1 is greater than n2, perform
modulo operation - n1 % n2 */
if(n1 > n2) {
n1 = n1 % n2;
}
/* Else perform modulo
operation - n2 % n1 */
else {
n2 = n2 % n1;
}
}
// If n1 is zero, GCD is stored in n2
if(n1 == 0) return n2;
//else GCD is stored in n1
return n1;
}
};
int main() {
int n1 = 4, n2 = 6;
/* Creating an instance of
Solution class */
Solution sol;
/* Function call to find the
gcd of two numbes */
int ans = sol.GCD(n1, n2);
cout << "GCD of " << n1 << " and " << n2 << " is: " << ans << endl;
return 0;
}
Complexity Analysis:
- Time Complexity:
O(log(min(N1, N2)))
– where N1 and N2 are given numbers. Because in every iteration, the algorithm is dividing larger number with the smaller number resulting in time complexity.(approx.) - Space Complexity:
O(1)
– Using a couple of variables i.e., constant space.