Open In App

Euclid’s Algorithm when % and / operations are costly

Euclid’s algorithm is used to find GCD of two numbers. 
There are mainly two versions of algorithm. 
Version 1 (Using subtraction) 
 




// Recursive function to return gcd of a and b
int gcd(int a, int b)
{
    if (a == b) 
        return a;
 
    return (a > b) ? gcd(a - b, b) : gcd(a, b - a);
}




// Recursive function to return gcd of a and b
int gcd(int a, int b)
{
    if (a == b) 
       return a;
  
    return (a > b)? gcd(a-b, b): gcd(a, b-a);
}




// Recursive function to return gcd of a and b
static int gcd(int a, int b)
{
    if (a == b)
        return a;
 
    return (a > b) ? gcd(a - b, b) : gcd(a, b - a);
}
 
// This code is contributed by subham348.




# Recursive function to return gcd of a and b
def gcd(a, b):
    if (a == b):
        return a
 
    return gcd(a-b, b) if (a > b) else gcd(a, b-a)
 
  # This code is contributed by subham348.




// Recursive function to return gcd of a and b
static int gcd(int a, int b)
{
    if (a == b)
        return a;
 
    return (a > b) ? gcd(a - b, b) : gcd(a, b - a);
}
 
// This code is contributed by subham348.




// Recursive function to return gcd of a and b
function gcd(a, b)
{
    if (a === b) 
       return a;
  
    return (a > b)? gcd(a-b, b): gcd(a, b-a);
}
 
// This code is contributed by subham348.

Time Complexity: O(max(a, b))

Auxiliary Space: O(1)

Version 2 (Using modulo operator) 
 




// Function to return gcd of a and b
static int gcd(int a, int b)
{
    if (a == 0)
       return b;
     
    return gcd(b % a, a);
}




// Function to return gcd of a and b
int gcd(int a, int b)
{
    if (a == 0)
       return b;
     
    return gcd(b%a, a);
}




// Function to return gcd of a and b
static int gcd(int a, int b)
{
    if (a == 0)
       return b;
     
    return gcd(b%a, a);
}
 
// This code is contributed by subham348.




// Function to return gcd of a and b
static int gcd(int a, int b)
{
    if (a == 0)
       return b;
     
    return gcd(b%a, a);
}
 
// This code is contributed by subham348.




// Function to return gcd of a and b
function gcd(a, b)
{
    if (a === 0)
       return b;
     
    return gcd(b%a, a);
}
 
// This code is contributed by subham348.




# Python3 Function to return gcd of a and b
def gcd(a, b):
 
    if (a == 0):
        return b
 
    return gcd(b % a, a)
 
# This code is contributed by phasing17

Time Complexity: O(log(max(a, b)))

Auxiliary Space: O(1)

Which of the above two is more efficient? 
Version 1 can take linear time to find the GCD, consider the situation when one of the given numbers is much bigger than the other. Version 2 is obviously more efficient as there are less recursive calls and takes logarithmic time.
Consider a situation where modulo operator is not allowed, can we optimize version 1 to work faster?
Below are some important observations. The idea is to use bitwise operators. We can find x/2 using x>>1. We can check whether x is odd or even using x&1.
gcd(a, b) = 2*gcd(a/2, b/2) if both a and b are even. 
gcd(a, b) = gcd(a/2, b) if a is even and b is odd. 
gcd(a, b) = gcd(a, b/2) if a is odd and b is even.
Below is C++ implementation.
 




// Efficient C++ program when % and / are not allowed
int gcd(int a, int b)
{
    // Base cases
    if (b == 0 || a == b)
        return a;
    if (a == 0)
        return b;
 
    // If both a and b are even, divide both a
    // and b by 2.  And multiply the result with 2
    if ((a & 1) == 0 && (b & 1) == 0)
        return gcd(a >> 1, b >> 1) << 1;
 
    // If a is even and b is odd, divide a by 2
    if ((a & 1) == 0 && (b & 1) != 0)
        return gcd(a >> 1, b);
 
    // If a is odd and b is even, divide b by 2
    if ((a & 1) != 0 && (b & 1) == 0)
        return gcd(a, b >> 1);
 
    // If both are odd, then apply normal subtraction
    // algorithm.  Note that odd-odd case always
    // converts odd-even case after one recursion
    return (a > b) ? gcd(a - b, b) : gcd(a, b - a);
}




// Efficient C++ program when % and / are not allowed
int gcd(int a, int b)
{
    // Base cases
    if (b == 0 || a == b) return a;
    if (a == 0) return b;
 
    // If both a and b are even, divide both a
    // and b by 2.  And multiply the result with 2
    if ( (a & 1) == 0 && (b & 1) == 0 )
       return gcd(a>>1, b>>1) << 1;
 
    // If a is even and b is odd, divide a by 2
    if ( (a & 1) == 0 && (b & 1) != 0 )
       return gcd(a>>1, b);
 
    // If a is odd and b is even, divide b by 2
    if ( (a & 1) != 0 && (b & 1) == 0 )
       return gcd(a, b>>1);
 
    // If both are odd, then apply normal subtraction
    // algorithm.  Note that odd-odd case always
    // converts odd-even case after one recursion
    return (a > b)? gcd(a-b, b): gcd(a, b-a);
}




// Java program to implement
// the above approach
 
import java.util.*;
 
class GFG {
 
    static int gcd(int a, int b)
    {
        // Base cases
        if (b == 0 || a == b)
            return a;
        if (a == 0)
            return b;
 
        // If both a and b are even, divide both a
        // and b by 2.  And multiply the result with 2
        if ((a & 1) == 0 && (b & 1) == 0)
            return gcd(a >> 1, b >> 1) << 1;
 
        // If a is even and b is odd, divide a by 2
        if ((a & 1) == 0 && (b & 1) != 0)
            return gcd(a >> 1, b);
 
        // If a is odd and b is even, divide b by 2
        if ((a & 1) != 0 && (b & 1) == 0)
            return gcd(a, b >> 1);
 
        // If both are odd, then apply normal subtraction
        // algorithm.  Note that odd-odd case always
        // converts odd-even case after one recursion
        return (a > b) ? gcd(a - b, b) : gcd(a, b - a);
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        System.out.println(gcd(54, 36));
    }
}
 
// This code is contributed by phasing17




def gcd(a, b):
    # Base cases
    if (b == 0 or a == b):
        return a
    if (a == 0):
        return b
    # If both a and b are even, divide both a and b by 2.
    # And multiply the result with 2
    if ((a & 1) == 0 and (b & 1) == 0):
        return gcd(a >> 1, b >> 1) * 2
    # If a is even and b is odd, divide a by 2
    if ((a & 1) == 0 and (b & 1) != 0):
        return gcd(a >> 1, b)
    # If a is odd and b is even, divide b by 2
    if ((a & 1) != 0 and (b & 1) == 0):
        return gcd(a, b >> 1)
    # If both are odd, then apply normal subtraction algorithm.
    # Note that odd-odd case always converts odd-even case after one recursion
    return gcd(a-b, b) if a > b else gcd(a, b-a)
 
# This code is contributed by Vikram_Shirsat




// C# program to implement
// the above approach
using System;
 
class GFG
{
 
  // Efficient C++ program when % and / are not allowed
  int gcd(int a, int b)
  {
    // Base cases
    if (b == 0 || a == b) return a;
    if (a == 0) return b;
 
    // If both a and b are even, divide both a
    // and b by 2.  And multiply the result with 2
    if ( (a & 1) == 0 && (b & 1) == 0 )
      return gcd(a>>1, b>>1) << 1;
 
    // If a is even and b is odd, divide a by 2
    if ( (a & 1) == 0 && (b & 1) != 0 )
      return gcd(a>>1, b);
 
    // If a is odd and b is even, divide b by 2
    if ( (a & 1) != 0 && (b & 1) == 0 )
      return gcd(a, b>>1);
 
    // If both are odd, then apply normal subtraction
    // algorithm.  Note that odd-odd case always
    // converts odd-even case after one recursion
    return (a > b)? gcd(a-b, b): gcd(a, b-a);
  }
 
}
 
// This code is contributed by code_hunt.




// Efficient JavaScript program when % and / are not allowed
function gcd(a, b)
{
    // Base cases
    if (b == 0 || a == b) return a;
    if (a == 0) return b;
 
    // If both a and b are even, divide both a
    // and b by 2.  And multiply the result with 2
    if ( (a & 1) == 0 && (b & 1) == 0 )
       return gcd(a>>1, b>>1) << 1;
 
    // If a is even and b is odd, divide a by 2
    if ( (a & 1) == 0 && (b & 1) != 0 )
       return gcd(a>>1, b);
 
    // If a is odd and b is even, divide b by 2
    if ( (a & 1) != 0 && (b & 1) == 0 )
       return gcd(a, b>>1);
 
    // If both are odd, then apply normal subtraction
    // algorithm.  Note that odd-odd case always
    // converts odd-even case after one recursion
    return (a > b)? gcd(a-b, b): gcd(a, b-a);
}
 
// This code is contributed by phasing17

Time Complexity: O(log(max(a, b)))

Auxiliary Space: O(1)

This article is compiled by Shivam Agrawal.
 


Article Tags :