0

I am trying to convert this recursive algorithm

isqrt(n){
if(n==0){
    return 0;
}
a = 2*isqrt(n/4)+1;
if(n<(a*a)){
    return a-1;
} else {
    return a;
}

}

into an iterative algorithm. So far I was able to do this:

isqrt(n){
vector c;
for(d = n; d>0; d = d/4){
    c.push_back(d);
}
res = 0;
for(con = c.size(); con>0; con = con-1){
    a = 2*res+1;
    if(c[con-1]<(a*a)){
        res = a-1;
    } else {
        res = a;
    }
}
return res;

}

This could be a solution to my problem, but my approach was simply "simulating the function stack" inside the function itself with the vector, which works but still runs in O(floor(log4(n))) space, which in my use case is greatly undesirable. Is there any way to modify this algorithm in an iterative algorithm that runs in O(1) space? If possible the time complexity should remain the same.

ThePirate42
  • 103
  • 5

1 Answers1

1

Converting it into an iterative algorithm is somewhat vague and there could be many different ways to do it. One way could be the following:

isqrt(n){
  if (n==0){
    return 0;
  }
  a = 1;
  b = a*a;
  while (true){
    if (n < b){
      return a-1;
    } else {
      b += 2*a+1;
      a += 1;
    }
  }
}

Other options can be applying Newton's algorithm.

There was the question in the comments about which number to use for the initial point in Newton's algorithm. One can use $x_0=n//2$. Any positive number will work.


There was also the question of ensuring logarithmic time complexity. Observe that in the set $[n]=\{0,1,2,\ldots,n\}$ the elements satisfying $x^2\leq n$ are all less than or equal to those satisfying $x^2\geq n$. The integer square root is the largest element of $[n]$ satisfying $x^2\leq n$. Therefore, we can find it using binary search.

isqrt(n){
  if (n==1){
    return n;
  }
  L = 0;
  R = n//2;
  while (L < R){
    m = L + (R-L)//2;
    s = m*m;
    if (L == m){
      if (s <= n){
        return L;
      } else {
        return R;
      }
    }
    if (s < n){
      L = m;
    } else if (s > m) {
      R = m;
    } else {
      return m;
    }
  }
  return L;
}
plop
  • 1,189
  • 5
  • 11