Блог пользователя Rishav_raj_

Автор Rishav_raj_, история, 10 месяцев назад, По-английски

GCD

  • Gcd of two natural number $$$a$$$ and $$$b$$$ is defined as the largest number which is a divisor of both $$$a$$$ and $$$b$$$.
  • Mathematically it is defined as: GCD(a, b)= max{k>0: (k/a) and (k/b)}.(Here $$$k$$$/$$$a$$$ means $$$k$$$ divides  $$$a$$$).

    Ways to find GCD

    Brute Force

  • We can find gcd of two number by checking for all integer less than both number.

  • We never use this approach to find gcd because this run in O(n) time complexity.

    Euclidean algorithm

  • The Euclidean algorithm was formulated as follows: subtract the smaller number from the larger one until one of the numbers is zero. Indeed, if   $$$g$$$ divides   $$$a$$$ and   $$$b$$$, it also divides   $$$a-b$$$. On the other hand, if   $$$g$$$ divides   $$$a-b$$$ and   $$$b$$$, then it also divides   $$$a = b + (a-b)$$$, which means that the sets of the common divisors of   $$${a, b}$$$ and   $$${b,a-b}$$$ coincide.

  • $$$a$$$ remains the larger number until   $$$b$$$ is subtracted from it at least   $$$\left\lfloor\frac{a}{b}\right\rfloor$$$ times. Therefore, to speed things up,   $$$a-b$$$ is substituted with $$$a-\left\lfloor\frac{a}{b}\right\rfloor b = a \bmod b$$$.

Implementation Using Code

1. Recursive Code

    int gcd (int a, int b) {
       if (b == 0)
        return a;
       else
     return gcd (b, a % b);
     }
This code run in O(log min(a, b)) Time complexity and in Recursive Stack space complexity.

2. Iterative Solution

    int gcd (int a, int b) {
      while (b) {
        a %= b;
        swap(a, b);
      }
      return a;
    }
This code run in O(log min(a, b)) Time complexity and But it take a constant space complexity as we have only define two variable only. This solution is is more faster than recursive one because of recursive call take more time than normal iteration.

Binary GCD

Above method works in time complexity of O(log n).we can more optimize this as we all know that The slow part of the normal algorithm are the modulo operations. Modulo operations, although we see them as   $$$O(1)$$$, are a lot slower than simpler operations like addition, subtraction or bitwise operations.. Here comes the Binary GCD in role.

This uses three very popular properties of GCD

  • If both numbers are even, then we can factor out a two of both and compute the GCD of the remaining numbers:   $$$\gcd(2a, 2b) = 2 \gcd(a, b)$$$.
  • If one of the numbers is even and the other one is odd, then we can remove the factor 2 from the even one:   $$$\gcd(2a, b) = \gcd(a, b)$$$ if   $$$b$$$ is odd.
  • If both numbers are odd, then subtracting one number of the other one will not change the GCD:   $$$\gcd(a, b) = \gcd(b, a-b)$$$

Implementation Using Code

    int gcd(int a, int b) {
      if (!a || !b)
        return a | b;
      unsigned shift = __builtin_ctz(a | b);
      a >>= __builtin_ctz(a);
      do {
        b >>= __builtin_ctz(b);
        if (a > b)
            swap(a, b);
        b -= a;
      } while (b);
     return a << shift;
    }

Thanks.

  • Проголосовать: нравится
  • -5
  • Проголосовать: не нравится

»
10 месяцев назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

How is the last algorithm O(1) in time complexity?

  • »
    »
    10 месяцев назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Not exactly O(1) but it can take maximum of O(32) time. Means it will only constant time complexity only which is appropriately to O(1).

    • »
      »
      »
      10 месяцев назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      This is false, it takes log(max(a, b)). this is like saying O(nlogn) is just O(32*n) which simplifies to O(n)

      • »
        »
        »
        »
        10 месяцев назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        No bro this code is more optimised than normal Euclidean algorithm. You may also well known that bit operation is much faster than any algebraic expressions. I agree and apologize that this code will will not take maximum of O(32).it will take more than that but this is more optimised than normal gcd function which runs in O(log(n)).

        • »
          »
          »
          »
          »
          10 месяцев назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится

          but from what i see, the worst case of this technique is still $$$O(\log (\max (a,b)))$$$ since it is possible that certain pairs $$$(a,b)$$$ will make it just be repeating 3rd and 2nd step once each repeatedly.

  • »
    »
    10 месяцев назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Not exactly O(1) but this is more optimised than normal Euclidean algorithm because this uses bit instead of modular operation.

»
10 месяцев назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Auto comment: topic has been updated by Rishav_raj_ (previous revision, new revision, compare).