I'm having trouble determining the worst case time complexity of this recursive function:
long f(int n) {
if(n <= 0) return 1;
else {
return f(n / 2) + f(n / 2) + f(n / 2);
}
}
I understand that if you were just returning f(n / 2) once, it would be O(log n). So I was wondering if having it three, four, five, etc times would affect the function's big O. Thanks!
Multiplying by a constant never affects the complexity. Of course, the execution time is roughly tripled, but the issue is how the time increases with respect to the value of n, not what the clock says.
Do note that this applies so easily because you're calling the same function with the same value; this could be reliably replaced by
return 3 * f(n/2)
If you had three different calls, such as
return f(n/2) + f(int(sqrt(n)) + f(n-1)
... then you'd have to compute the complexity of each and consider only the most complex. That isn't hard with this function; however, with a more complex function, such as the Collatz sequence, you'd have a more difficult time considering all of the 2nd- and 3rd-order complexities. You would also have more trouble with a call to an indirectly recursive function, such as
long f(int n);
long g(int n) {
if(n <= 2) return 1;
else {
return f(n*n mod 10) + g(n-2);
}
}
long f(int n) {
if(n <= 0) return 1;
else {
return f(n / 2) + g(n / 2);
}
}
Bottom line: your question is simple, but beware of follow-up questions.
Related
I'm trying to write a function to find the lowest number that all integers between 1 and 20 divide. (Let's call this Condition D)
Here's my solution, which is somehow exceeding the call stack size limit.
function findSmallest(num){
var count = 2
while (count<21){
count++
if (num % count !== 0){
// exit the loop
return findSmallest(num++)
}
}
return num
}
console.log(findSmallest(20))
Somewhere my reasoning on this is faulty but here's how I see it (please correct me where I'm wrong):
Calling this function with a number N that doesn't meet Condition D will result in the function being called again with N + 1. Eventually, when it reaches a number M that should satisfy Condition D, the while loop runs all the way through and the number M is returned by the function and there are no more recursive calls.
But I get this error on running it:
function findSmallest(num){
^
RangeError: Maximum call stack size exceeded
I know errors like this are almost always due to recursive functions not reaching a base case. Is this the problem here, and if so, where's the problem?
I found two bugs.
in your while loop, the value of count is 3 to 21.
the value of num is changed in loop. num++ should be num + 1
However, even if these bugs are fixed, the error will not be solved.
The answer is 232792560.
This recursion depth is too large, so stack memory exhausted.
For example, this code causes same error.
function foo (num) {
if (num === 0) return
else foo(num - 1)
}
foo(232792560)
Coding without recursion can avoid errors.
Your problem is that you enter the recursion more than 200 million times (plus the bug spotted in the previous answer). The number you are looking for is the multiple of all prime numbers times their max occurrences in each number of the defined range. So here is your solution:
function findSmallestDivisible(n) {
if(n < 2 || n > 100) {
throw "Numbers between 2 and 100 please";
}
var arr = new Array(n), res = 2;
arr[0] = 1;
arr[1] = 2;
for(var i = 2; i < arr.length; i++) {
arr[i] = fix(i, arr);
res *= arr[i];
}
return res;
}
function fix(idx, arr) {
var res = idx + 1;
for(var i = 1; i < idx; i++) {
if((res % arr[i]) == 0) {
res /= arr[i];
}
}
return res;
}
https://jsfiddle.net/7ewkeamL/
I've several confusion about tail recursion as follows:
some of the recursion functions are void functions for example,
// Prints the given number of stars on the console.
// Assumes n >= 1.
void printStars(int n) {
if (n == 1) {
// n == 1, base case
cout << "*";
} else {
// n > 1, recursive case
cout << "*"; // print one star myself
printStars(n - 1); // recursion to do the rest
}
}
and another example:
// Prints the given integer's binary representation.
// Precondition: n >= 0
void printBinary(int n) {
if (n < 2) {
// base case; same as base 10
cout << n;
} else {
// recursive case; break number apart
printBinary(n / 2);
printBinary(n % 2);
}
}
As we know by definition tail recursion should return some value from tail call. But for void functions it does not return any value. By intinction I think they are tail recursion but I am not confident about it.
another question is that, if a recursion function has several logical end, should tail recursion come at all logical ends or just one of the logical ends? I saw someone argued that only one of the logical ends is OK, but I am not sure about that. Here's my example:
// Returns base ^ exp.
// Precondition: exp >= 0
int power(int base, int exp) {
if (exp < 0) {
throw "illegal negative exponent";
} else if (exp == 0) {
// base case; any number to 0th power is 1
return 1;
} else if (exp % 2 == 0) {
// recursive case 1: x^y = (x^2)^(y/2)
return power(base * base, exp / 2);
} else {
// recursive case 2: x^y = x * x^(y-1)
return base * power(base, exp - 1);
}
}
Here we have logical end as tail recursion and another one that is not tail recursion. Do you think this function is tail recursion or not? why?
I have written a simple fibonacci series using recursion as below. But the below program is based on the formula fib(n)=fib(n-1)+fib(n-2).
Can we write a program to take a value of n and compute the fibonacci series using the formula fib(n+2)= fib(n)+fib(n+1). Can we write a program based on this formulae taking n as input.
public class FibonacciClass{
public static void main(String[] argv){
for (int index=0; index < 7; index++){
System.out.println("The Fibonacci series for the number "+index+" is " + fib(index));
}
}
private static int fib(int n){
if (n == 0 ) return 0;
if (n <= 2 ) return 1;
return (fib(n-1) + fib(n-2));
}
}
If we can solve the fib series using recursion, please let me know your inputs to write the program for the same.
hmm this sounds like you're trying to get an answer to a homework problem. But looks like you have legitimate reputation so:
Define
gib(n) = fib(n+2).
Use this to substitute for fib(n) and fib(n+1):
gib(n-2) = fib((n-2)+2) = fib(n)
gib(n-1) = fib((n-1)+2) = fib(n+1)
So the original equation becomes
fib(n+2)= fib(n)+fib(n+1) --> gib(n) = gib(n-2) + gib(n-1)
And we can recurse on this. We must make similar substitutions (n for n+2) in the code:
static unsigned int gib(int n)
{
if (n <= -2) return 0;
if (n == -1) return 1;
return gib(n - 2) + gib(n - 1);
}
I didnt include negative numbers that result in negative fibonacci (your code breaks on them too) so truly it needs to be returning "unsigned int". To modify for negative see here.
I have encountered the following problem:
N is positive non-zero integer and I have to calculate the product of : N*(N-1)^2*(N-2)^3*..*1^N.
My solution so far is as follows:
N*myFact(N-1)*fact(N-1)
The thing is I'm not allowed to use any helping functions, such as 'fact()'.
EDIT: Mathematically it can be represented as follows: N!*(N-1)! (N-2)!..*1!
This function is called the superfactorial. A recursive implementation is
long superFact(n) {
if (n < 2) return 1;
long last = superFact(n-1);
long prev = superFact(n-2);
return last * last / prev * n;
}
but this is very inefficient -- it takes about 3*F(n) recursive calls to find superFact(n), where F(n) is the n-th Fibonacci number. (The work grows exponentially.)
Try:
int myFact(int n) {
return n == 1 ? 1 : myFact(n-1)*n;
}
I assume this needs to be accomplished with 1 function i.e. you're not allowed to create a fact helper function yourself.
You can use the fact that myFact(n-1) / myFact(n-2) == (n-1)!
int myFact(int n)
{
if (n == 0 || n == 1) {
return 1
} else {
// (n - 1)!
int previousFact = myFact(n - 1) / myFact(n - 2);
return myFact(n - 1) * previousFact * n;
}
}
What is the Big-O time complexity ( O ) of the following recursive code?
public static int abc(int n) {
if (n <= 2) {
return n;
}
int sum = 0;
for (int j = 1; j < n; j *= 2) {
sum += j;
}
for (int k = n; k > 1; k /= 2) {
sum += k;
}
return abc(n - 1) + sum;
}
My answer is O(n log(n)). Is it correct?
Where I'm sitting...I think the runtime is O(n log n). Here's why.
You are making n calls to the function. The function definitely depends on n for the number of times the following two operations are made:
You loop up to 2*log(n) values to increment a sum.
For a worst case, n is extremely large, but the overall runtime doesn't change. A best case would be that n <= 2, such that only one operation is done (the looping would not occur).