1979. Find Greatest Common Divisor of Array
Problem Description
You are given an integer array nums
. Your task is to find the greatest common divisor (GCD) between the smallest and largest numbers in the array.
The greatest common divisor of two numbers is the largest positive integer that divides both numbers evenly (with no remainder).
For example:
- If
nums = [2, 5, 6, 9, 10]
, the smallest number is2
and the largest is10
. The GCD of2
and10
is2
. - If
nums = [7, 5, 6, 8, 3]
, the smallest number is3
and the largest is8
. The GCD of3
and8
is1
.
The solution involves:
- Finding the minimum value in the array using
min(nums)
- Finding the maximum value in the array using
max(nums)
- Computing the GCD of these two values using the built-in
gcd()
function
The gcd()
function from Python's math module efficiently calculates the greatest common divisor using the Euclidean algorithm. The time complexity is O(n)
for finding min/max values, and O(log(min(a,b)))
for computing the GCD where a
and b
are the two numbers.
Intuition
The problem asks for the GCD of two specific numbers from the array - the smallest and the largest. This immediately tells us we don't need to consider all elements in the array, just these two extremes.
Why just these two? The problem explicitly states we need the GCD of the minimum and maximum values. This simplifies our task significantly - instead of dealing with the entire array, we reduce it to a two-number GCD problem.
The key insight is that this is really two separate sub-problems:
- Finding the extremes (min and max) in the array
- Finding the GCD of two numbers
For finding extremes, we can simply scan through the array once. Python provides built-in min()
and max()
functions that do exactly this.
For finding the GCD, we could implement our own algorithm (like the Euclidean algorithm where we repeatedly apply gcd(a, b) = gcd(b, a % b)
until b
becomes 0), but Python's math module already provides an optimized gcd()
function.
The beauty of this approach is its directness - we identify exactly what we need (min, max, and their GCD) and use the most straightforward tools available to get them. There's no need for sorting the entire array or checking GCDs of multiple pairs. We go straight to the answer by focusing only on the two values that matter.
Learn more about Math patterns.
Solution Approach
The solution follows a straightforward simulation approach as mentioned in the reference. We directly implement what the problem asks for in three simple steps:
-
Find the maximum value in the array: We use Python's built-in
max()
function which iterates through the array once to find the largest element. This takesO(n)
time wheren
is the length of the array. -
Find the minimum value in the array: Similarly, we use Python's built-in
min()
function to find the smallest element. This also takesO(n)
time. -
Calculate the GCD: We use the
gcd()
function from Python's math module to compute the greatest common divisor of the max and min values found in steps 1 and 2.
The implementation is remarkably concise:
return gcd(max(nums), min(nums))
This single line:
- Calls
max(nums)
to get the largest value - Calls
min(nums)
to get the smallest value - Passes both values to
gcd()
to compute their greatest common divisor - Returns the result
The gcd()
function internally uses the Euclidean algorithm, which works by repeatedly replacing the larger number with the remainder of dividing the larger by the smaller, until one number becomes 0. The other number at that point is the GCD.
For example, if we have gcd(10, 2)
:
10 % 2 = 0
, so the GCD is2
Or for gcd(8, 3)
:
8 % 3 = 2
3 % 2 = 1
2 % 1 = 0
, so the GCD is1
The time complexity is O(n + log(min(a,b)))
where n
is the array length (for finding min/max) and a
, b
are the two numbers being processed for GCD. The space complexity is O(1)
as we only store two values regardless of input size.
Ready to land your dream job?
Unlock your dream job with a 3-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through the solution with a concrete example: nums = [12, 8, 3, 14, 6]
Step 1: Find the minimum value
- Scan through the array: 12, 8, 3, 14, 6
- The minimum value is
3
Step 2: Find the maximum value
- Scan through the same array: 12, 8, 3, 14, 6
- The maximum value is
14
Step 3: Calculate GCD(14, 3) Using the Euclidean algorithm:
14 % 3 = 2
(14 = 3 × 4 + 2)- Now compute GCD(3, 2)
3 % 2 = 1
(3 = 2 × 1 + 1)- Now compute GCD(2, 1)
2 % 1 = 0
(2 = 1 × 2 + 0)- When we reach 0, the other number (1) is our GCD
Result: GCD(3, 14) = 1
Let's verify with another example: nums = [20, 40, 10, 30]
Step 1: Find minimum → 10
Step 2: Find maximum → 40
Step 3: Calculate GCD(40, 10)
40 % 10 = 0
(40 = 10 × 4 + 0)- When remainder is 0, the divisor (10) is our GCD
Result: GCD(10, 40) = 10
The complete solution in code would be:
from math import gcd
def findGCD(nums):
return gcd(max(nums), min(nums))
This elegantly combines all three steps into a single line, letting Python's built-in functions handle the heavy lifting while maintaining clarity and efficiency.
Solution Implementation
1from typing import List
2from math import gcd
3
4class Solution:
5 def findGCD(self, nums: List[int]) -> int:
6 """
7 Find the greatest common divisor (GCD) of the smallest and largest elements in the array.
8
9 Args:
10 nums: List of integers
11
12 Returns:
13 The GCD of the minimum and maximum values in nums
14 """
15 # Find the minimum and maximum values in the array
16 min_value = min(nums)
17 max_value = max(nums)
18
19 # Calculate and return the GCD of these two values
20 return gcd(max_value, min_value)
21
1class Solution {
2 /**
3 * Finds the greatest common divisor (GCD) of the largest and smallest elements in the array.
4 *
5 * @param nums the input array of positive integers
6 * @return the GCD of the maximum and minimum elements
7 */
8 public int findGCD(int[] nums) {
9 // Initialize max to smallest possible value and min to largest possible value
10 int maxElement = 1;
11 int minElement = 1000;
12
13 // Iterate through array to find maximum and minimum elements
14 for (int num : nums) {
15 maxElement = Math.max(maxElement, num);
16 minElement = Math.min(minElement, num);
17 }
18
19 // Calculate and return the GCD of max and min elements
20 return gcd(maxElement, minElement);
21 }
22
23 /**
24 * Calculates the greatest common divisor using Euclidean algorithm.
25 *
26 * @param a the first number
27 * @param b the second number
28 * @return the GCD of a and b
29 */
30 private int gcd(int a, int b) {
31 // Base case: when b becomes 0, a is the GCD
32 // Recursive case: GCD(a, b) = GCD(b, a % b)
33 return b == 0 ? a : gcd(b, a % b);
34 }
35}
36
1class Solution {
2public:
3 int findGCD(vector<int>& nums) {
4 // Find the minimum and maximum elements in the array
5 // minmax_element returns a pair of iterators pointing to min and max elements
6 auto minMaxPair = ranges::minmax_element(nums);
7
8 // Extract the minimum value by dereferencing the first iterator
9 int minValue = *minMaxPair.first;
10
11 // Extract the maximum value by dereferencing the second iterator
12 int maxValue = *minMaxPair.second;
13
14 // Calculate and return the GCD of the minimum and maximum values
15 // std::gcd is a built-in function that computes the greatest common divisor
16 return gcd(minValue, maxValue);
17 }
18};
19
1/**
2 * Finds the greatest common divisor (GCD) of the minimum and maximum values in an array
3 * @param nums - Array of positive integers
4 * @returns The GCD of the minimum and maximum values
5 */
6function findGCD(nums: number[]): number {
7 // Find the minimum value in the array
8 const min: number = Math.min(...nums);
9
10 // Find the maximum value in the array
11 const max: number = Math.max(...nums);
12
13 // Calculate and return the GCD of min and max
14 return gcd(min, max);
15}
16
17/**
18 * Calculates the greatest common divisor of two numbers using Euclidean algorithm
19 * @param a - First positive integer
20 * @param b - Second positive integer
21 * @returns The greatest common divisor of a and b
22 */
23function gcd(a: number, b: number): number {
24 // Base case: if b is 0, then GCD is a
25 if (b === 0) {
26 return a;
27 }
28
29 // Recursive case: GCD(a, b) = GCD(b, a mod b)
30 return gcd(b, a % b);
31}
32
Time and Space Complexity
Time Complexity: O(n + log(min(a, b)))
, where n
is the length of the array nums
, a = max(nums)
, and b = min(nums)
.
- Finding the maximum element:
O(n)
- requires traversing the entire array once - Finding the minimum element:
O(n)
- requires traversing the entire array once - Computing GCD using Euclidean algorithm:
O(log(min(a, b)))
wherea
andb
are the two numbers
Since the GCD computation time is typically much smaller than n
for practical inputs, the overall time complexity is dominated by O(n)
.
Space Complexity: O(1)
- The
max()
andmin()
functions use constant extra space - The
gcd()
function (Euclidean algorithm) uses constant extra space for its internal computations - No additional data structures are created that scale with input size
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Not Handling Edge Cases with Single Element Arrays
While the provided solution works correctly for arrays with multiple elements, a common pitfall is not considering what happens when the array contains only one element. In this case, both the minimum and maximum values are the same number.
Issue: When nums = [5]
, both min and max are 5
, so we're computing gcd(5, 5)
.
Why it's actually fine: The GCD of a number with itself is the number itself, so gcd(5, 5) = 5
, which is mathematically correct. The provided solution handles this case properly without any special logic needed.
2. Assuming Import of gcd is Automatic
A common mistake is forgetting to import the gcd
function from the math module, leading to a NameError
.
Incorrect approach:
class Solution:
def findGCD(self, nums: List[int]) -> int:
return gcd(max(nums), min(nums)) # NameError: name 'gcd' is not defined
Correct approach:
from math import gcd # Don't forget this import!
class Solution:
def findGCD(self, nums: List[int]) -> int:
return gcd(max(nums), min(nums))
3. Implementing Custom GCD Without Understanding Edge Cases
Some developers might try to implement their own GCD function without fully understanding the algorithm, leading to infinite loops or incorrect results.
Problematic custom implementation:
def custom_gcd(a, b):
while b:
a, b = b, a % b
return a
class Solution:
def findGCD(self, nums: List[int]) -> int:
return custom_gcd(max(nums), min(nums))
Issue: While this implementation is actually correct, developers might make mistakes like:
- Not handling the case where
b
is initially larger thana
- Using
a / b
instead ofa % b
(division instead of modulo) - Not updating both variables correctly in the loop
Better approach: Use the built-in math.gcd()
which is thoroughly tested and optimized.
4. Unnecessary Multiple Passes Through the Array
Some might make multiple passes through the array unnecessarily:
Inefficient approach:
class Solution:
def findGCD(self, nums: List[int]) -> int:
nums.sort() # O(n log n) - unnecessary sorting!
return gcd(nums[-1], nums[0])
Why it's inefficient: Sorting takes O(n log n) time when we only need O(n) to find min and max values.
Optimal approach: Use min()
and max()
functions which each make a single O(n) pass through the array.
Consider the classic dynamic programming of fibonacci numbers, what is the recurrence relation?
Recommended Readings
Math for Technical Interviews How much math do I need to know for technical interviews The short answer is about high school level math Computer science is often associated with math and some universities even place their computer science department under the math faculty However the reality is that you
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Want a Structured Path to Master System Design Too? Don’t Miss This!