GCD and LCM Euclidean Algorithm in DSA Go - Time & Space Complexity
We want to understand how fast the Euclidean algorithm finds the greatest common divisor (GCD) of two numbers.
This helps us know how the steps grow when numbers get bigger.
Analyze the time complexity of the following code snippet.
func gcd(a, b int) int {
for b != 0 {
a, b = b, a % b
}
return a
}
func lcm(a, b int) int {
return a / gcd(a, b) * b
}
This code finds the GCD of two numbers using the Euclidean algorithm and then calculates the LCM using the GCD.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The loop repeatedly replaces numbers with their remainder until the remainder is zero.
- How many times: The loop runs as many times as needed to reduce the smaller number to zero by taking remainders.
Each step reduces the numbers significantly, so the number of steps grows slowly even if numbers get very large.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 5 steps |
| 100 | About 7 steps |
| 1000 | About 10 steps |
Pattern observation: The steps grow roughly proportional to the number of digits, not the number size itself.
Time Complexity: O(log min(a, b))
This means the time to find the GCD grows slowly, roughly with the number of digits of the smaller input.
[X] Wrong: "The Euclidean algorithm takes as many steps as the size of the numbers themselves."
[OK] Correct: Each step reduces the problem size quickly by using remainders, so it takes far fewer steps than the number size.
Understanding this algorithm's time complexity shows you can analyze efficient number operations, a useful skill in many coding problems.
"What if we used subtraction instead of remainder in the loop? How would the time complexity change?"
Practice
a and b?Solution
Step 1: Understand the Euclidean algorithm purpose
The Euclidean algorithm is a method to find the greatest common divisor (GCD) of two integers by repeatedly applying the remainder operation.Step 2: Differentiate GCD from LCM
While GCD finds the largest number dividing both, LCM finds the smallest number divisible by both. Euclidean algorithm is for GCD.Final Answer:
The Greatest Common Divisor (GCD) -> Option CQuick Check:
Euclidean algorithm = GCD [OK]
- Confusing GCD with LCM
- Thinking it calculates sum or difference
- Assuming it finds prime factors directly
a and b?Solution
Step 1: Check recursive Euclidean algorithm syntax
func gcd(a, b int) int { if b == 0 { return a } return gcd(b, a % b) } uses recursion and modulo operation correctly: if b is zero, return a; else call gcd(b, a % b).Step 2: Verify other options for correctness
func gcd(a, b int) int { return a + b } returns sum, C returns first divisor found (incorrect logic), D returns product. Only A is correct.Final Answer:
func gcd(a, b int) int { if b == 0 { return a } return gcd(b, a % b) } -> Option AQuick Check:
Correct recursive gcd code = func gcd(a, b int) int { if b == 0 { return a } return gcd(b, a % b) } [OK]
- Returning sum or product instead of GCD
- Incorrect loop logic for GCD
- Missing base case for recursion
package main
import "fmt"
func gcd(a, b int) int {
if b == 0 {
return a
}
return gcd(b, a % b)
}
func lcm(a, b int) int {
return (a * b) / gcd(a, b)
}
func main() {
fmt.Println(gcd(12, 18))
fmt.Println(lcm(12, 18))
}Solution
Step 1: Calculate gcd(12, 18) using Euclidean algorithm
18 % 12 = 6, gcd(12, 6) -> 12 % 6 = 0, gcd(6, 0) = 6. So gcd is 6.Step 2: Calculate lcm(12, 18) using formula
LCM = (12 * 18) / 6 = 216 / 6 = 36.Final Answer:
6 36 -> Option AQuick Check:
GCD=6, LCM=36 [OK]
- Mixing up GCD and LCM values
- Incorrect modulo calculations
- Forgetting integer division
func gcd(a, b int) int {
for b != 0 {
a = b
b = a % b
}
return a
}Solution
Step 1: Analyze the assignment order inside the loop
Assigninga = bfirst changesabefore calculatingb = a % b, soa % buses updateda, causing wrong result.Step 2: Correct approach for Euclidean algorithm
Storea % bin a temp variable before updatinga, or swap assignments to avoid overwriting needed values.Final Answer:
The order of assignments causes incorrect modulo calculation -> Option DQuick Check:
Assignment order matters in Euclidean GCD [OK]
- Overwriting variables before modulo calculation
- Wrong loop condition
- Returning wrong variable
a and b, which of the following Go functions correctly computes the LCM using the Euclidean algorithm for GCD, handling the edge case when either a or b is zero?Solution
Step 1: Understand LCM edge cases
If eitheraorbis zero, LCM should be zero because zero times any number is zero.Step 2: Check each option for correct edge handling
func lcm(a, b int) int { if a == 0 || b == 0 { return 0 } return (a * b) / gcd(a, b) } returns 0 if either input is zero, then calculates LCM correctly. func lcm(a, b int) int { return (a * b) / gcd(a, b) } misses zero check. func lcm(a, b int) int { if a == 0 && b == 0 { return 1 } return (a + b) / gcd(a, b) } returns 1 incorrectly. func lcm(a, b int) int { if a == 0 || b == 0 { return 1 } return (a * b) / gcd(a, b) } returns 1 for zero inputs, which is wrong.Final Answer:
func lcm(a, b int) int { if a == 0 || b == 0 { return 0 } return (a * b) / gcd(a, b) } -> Option BQuick Check:
LCM zero if any input zero [OK]
- Ignoring zero inputs in LCM calculation
- Returning 1 instead of 0 for zero inputs
- Using addition instead of multiplication
Ready to prove it?
Pass the test and this pattern moves unknown
