Number of Fibonacci numbers smaller than number k. Sub O(n) - algorithm

Interview question: How many Fibonacci numbers exists less than a given number k? Can you find a function in terms of k, to get the number of fibonacci number less than k?
Example : n = 6
Answer: 6 as (0, 1, 1, 2, 3, 5)
Easy enough, write a loop or use the recursive definition of Fibonacci. However, that sounds too easy... is there a way to do this using the closed-form definition? (https://en.wikipedia.org/wiki/Fibonacci_number#Closed-form_expression)

Here is a close-form Python solution which is O(1). It uses Binet's formula (from the Wikipedia article that you linked to):
>>> from math import sqrt,log
>>> def numFibs(n): return int(log(sqrt(5)*n)/log((1+sqrt(5))/2))
>>> numFibs(10)
6
Which tracks with 1,1,2,3,5,8
The point is that the second term in Binet's formula is negligible and it is easy enough to invert the result of neglecting it.
The above formula counts the number of Fibonacci numbers which are less than or equal to n. It jumps by 1 with each new Fibonacci number. So, for example, numFibs(12) = 6 and numFibs(13) = 7. 13 is the 7th Fibonacci number, so if you want the number of Fibobacci numbers which are strictly smaller than n you have to introduce a lag. Something like:
def smallerFibs(n):
if n <= 1:
return 0
else:
return min(numFibs(n-1),numFibs(n))
Now smallerFibs(13) is still 6 but then smallerFibs(14) = 7. This is of course still O(1).

I think it's fairly easy to see the growth of this number, at least. By the Binet / De-Moivre formula,
fn = (φn - ψn) / 5
Since |ψ| < 1 < φ, then
fn ∼ φn / 5.
From this it follows that the number of Fibonacci numbers smaller than x grows like logφ(5x).

Related

Efficient Prime Factorization Algorithm with List of Prime Numbers

I am trying to implement an efficient algorithm, that can find the prime factorization for a given number n. I also have a list of all prime numbers up to at least n.
An example: If I have a number n = 50, the result should be: 2, 5, 5.
My ideas so far:
Check if n == 1, if true return 1
Check if n == 2, if true return 2
If both 1. and 2. are false:
Divide n by 2 as often as possible and add 2 to the vector of results
Try to find the (possibly by 2 divided) n in the list of prime numbers.
If n is in the list, add it to the results and return the results.
Find the largest prime number in the list, that is smaller than n.
Divide by the prime number found in step 6. If division without rest is possible, add the prime number to the results.
Check if n==1 and return the result if true
Repeat the steps 5-9.
Is that algorithm efficient or do you have any ideas for improvement?
Your proposed algorithm is inefficient. You should divide not by the largest remaining prime, but by the smallest. And if the smallest squared is larger than what is left, what is left is prime.
Your existing algorithm will need O(n/log(n)) divisions on average. My improvement makes it O(sqrt(n)/log(n)) instead. Which is still not a particularly efficient factorization algorithm. But is fine out to a few million.

Efficiently generate primes in Python and calculate complexity

Generating prime numbers from 1 to n Python 3. How to improve efficiency and what is the complexity?
Input: A number, max (a large number)
Output: All the primes from 1 to max
Output is in the form of a list and will be [2,3,5,7,11,13,.......]
The code attempts to perform this task in an efficient way (least time complexity).
from math import sqrt
max = (10**6)*3
print("\nThis code prints all primes till: " , max , "\n")
list_primes=[2]
def am_i_prime(num):
"""
Input/Parameter the function takes: An integer number
Output: returns True, if the number is prime and False if not
"""
decision=True
i=0
while(list_primes[i] <= sqrt(num)): #Till sqrt(n) to save comparisons
if(num%list_primes[i]==0):
decision=False
break
#break is inserted so that we get out of comparisons faster
#Eg. for 1568, we should break from the loop as soon as we know that 1568%2==0
i+=1
return decision
for i in range(3,max,2): #starts from 3 as our list contains 2 from the beginning
if am_i_prime(i)==True:
list_primes.append(i) #if a number is found to be prime, we append it to our list of primes
print(list_primes)
How can I make this faster? Where can I improve?
What is the time complexity of this code? Which steps are inefficient?
In what ways is the Sieve of Eratosthenes more efficient than this?
Working for the first few iterations:-
We have a list_primes which contains prime numbers. It initially contains only 2.
We go to the next number, 3. Is 3 divisible by any of the numbers in list_primes? No! We append 3 to list_primes. Right now, list_primes=[2,3]
We go to the next number 4. Is 4 divisible by any of the numbers in list_primes? Yes (4 is divisible by 2). So, we don't do anything. Right now list_primes=[2,3]
We go to the next number, 5. Is 5 divisible by any of the numbers in list_primes? No! We append 5 to list_primes. Right now, list_primes=[2,3,5]
We go to the next number, 6. Is 6 divisible by any of the numbers in list_primes? Yes (6 is divisible by 2 and also divisible by 3). So, we don't do anything. Right now list_primes=[2,3,5]
And so on...
Interestingly, it takes a rather deep mathematical theorem to prove that your algorithm is correct at all. The theorem is: "For every n ≥ 2, there is a prime number between n and n^2". I know it has been proven, and much stricter bounds are proven, but I must admit I wouldn't know how to prove it myself. And if this theorem is not correct, then the loop in am_i_prime can go past the bounds of the array.
The number of primes ≤ k is O (k / log k) - this is again a very deep mathematical theorem. Again, beyond me to prove.
But anyway, there are about n / log n primes up to n, and for these primes the loop will iterate through all primes up to n^(1/2), and there are O (n^(1/2) / log n) of them.
So for the primes alone, the runtime is therefore O (n^1.5 / log^2 n), so that is a lower bound. With some effort it should be possible to prove that for all numbers, the runtime is asymptotically the same.
O (n^1.5 / log n) is obviously an upper bound, but experimentally the number of divisions to find all primes ≤ n seems to be ≤ 2 n^1.5 / log^2 n, where log is the natural logarithm.
The following rearrangement and optimization of your code will reach your maximum in nearly 1/2 the time of your original code. It combines your top level loop and predicate function into a single function to eliminate overhead and manages squares (square roots) more efficiently:
def get_primes(maximum):
primes = []
if maximum > 1:
primes.append(2)
squares = [4]
for number in range(3, maximum, 2):
i = 0
while squares[i] <= number:
if number % primes[i] == 0:
break
i += 1
else: # no break
primes.append(number)
squares.append(number * number)
return primes
maximum = 10 ** 6 * 3
print(get_primes(maximum))
However, a sieve-based algorithm will easily beat this (as it avoids division and/or multiplication). Your code has a bug: setting max = 1 will create the list [2] instead of the correct answer of an empty list. Always test both ends of your limits.
O(N**2)
Approximately speaking, the first call to am_I_prime does 1 comparison, the second does 2, ..., so the total count is 1 + 2 + ... + N, which is (N * (N-1)) / 2, which has order N-squared.

How many numbers have a maximum number of unique prime factors in a given range

Note that the divisors have to be unique
So 32 has 1 unique prime factor [2], 40 has [2, 5] and so on.
Given a range [a, b], a, b <= 2^31, we should find how many numbers in this range have a maximum number of unique divisors.
The best algorithm I can imagine is an improved Sieve of Eratosthenes, with an array counting how many prime factors a number has. But it is not only O(n), which is unacceptable with such a range, but also very inefficient in terms of memory.
What is the best algorithm to solve this question? Is there such an algorithm?
I'll write a first idea in Python-like pseudocode. First find out how many prime factors you may need at most:
p = 1
i = 0
while primes[i] * p <= b:
p = p * primes[i]
i = i + 1
This only used b, not a, so you may have to decrease the number of actual prime factors. But since the result of the above is at most 9 (as the product of the first 10 primes already exceeds 231), you can conceivably go down from this maximum one step at a time:
cnt = 0
while cnt == 0:
cnt = count(i, 1, 0)
i = i - 1
return cnt
So now we need to implement this function count, which I define recursively.
def count(numFactorsToGo, productSoFar, nextPrimeIndex):
if numFactorsToGo > 0:
cnt = 0
while productSoFar * primes[nextPrimeIndex] <= b:
cnt = cnt + count(numFactorsToGo - 1,
productSoFar * primes[nextPrimeIndex],
nextPrimeIndex + 1)
nextPrimeIndex = nextPrimeIndex + 1
return cnt
else:
return floor(b / productSoFar) - ceil(a / productSoFar) + 1
This function has two cases to distinguish. In the first case, you don't have the desired number of prime factors yet. So you multiply in another prime, which has to be larger than the largest prime already included in the product so far. You achieve this by starting at the given index for the next prime. You add the counts for all these recursive calls.
The second case is where you have reached the desired number of prime factors. In this case, you want to count all possible integers k such that a ≤ k∙p ≤ b. Which translates easily into ⌈a/p⌉ ≤ k ≤ ⌊b/p⌋ so the count would be ⌊b/p⌋ − ⌈a/p⌉ + 1. In an actual implementation I'd not use floating-point division and floor or ceil, but instead I'd make use of truncating integer division for the sake of performance. So I'd probably write this line as
return (b // productSoFar) - ((a - 1) // productSoFar + 1) + 1
As it is written now, you'd need the primes array precomouted up to 231, which would be a list of 105,097,565 numbers according to Wolfram Alpha. That will cause considerable memory requirements, and will also make the outer loops (where productSoFar is still small) iterate over a large number of primes which won't be needed later on.
One thing you can do is change the end of loop condition. Instead of just checking that adding one more prime doesn't make the product exceed b, you can check whether including the next primesToGo primes in the product is possible without exceeding b. This will allow you to end the loop a lot earlier if the total number of prime factors is large.
For a small number of prime factors, things are still tricky. In particular if you have a very narrow range [a, b] then the number with maximal prime factor count might well be a large prime factor times a product of very small primes. Consider for example [2147482781, 2147482793]. This interval contains 4 elements with 4 distinct factors, some of which contain quite large prime factors, namely
3 ∙ 5 ∙ 7 ∙ 20,452,217
22 ∙ 3 ∙ 11 ∙ 16,268,809
2 ∙ 5 ∙ 19 ∙ 11,302,541
23 ∙ 7 ∙ 13 ∙ 2,949,839
Since there are only 4,792 primes up to sqrt(231), with 46,337 as their largest (which fits into a 16 bit unsigned integer). It would be possible to precompute only those, and use that to factor each number in the range. But that would again mean iterating over the range. Which makes sense for small ranges, but not for large ones.
So perhaps you need to distinguish these cases up front, and then choose the algorithm accordingly. I don't have a good idea of how to combine these ideas – yet. If someone else does, feel free to extend this post or write your own answer building on this.

Is this number a power of two?

I have a number (in base 10) represented as a string with up to 10^6 digits. I want to check if this number is a power of two. One thing I can think of is binary search on exponents and using FFT and fast exponentiation algorithm, but it is quite long and complex to code. Let n denote the length of the input (i.e., the number of decimal digits in the input). What's the most efficient algorithm for solving this problem, as a function of n?
There are either two or three powers of 2 for any given size of a decimal number, and it is easy to guess what they are, since the size of the decimal number is a good approximation of its base 10 logarithm, and you can compute the base 2 logarithm by just multiplying by an appropriate constant (log210). So a binary search would be inefficient and unnecessary.
Once you have a trial exponent, which will be on the order of three million, you can use the squaring exponentiation algorithm with about 22 bugnum decimal multiplications. (And up to 21 doublings, but those are relatively easy.)
Depending on how often you do this check, you might want to invest in fast bignum code. But if it is infrequent, simple multiplication should be ok.
If you don't expect the numbers to be powers of 2, you could first do a quick computation mod 109 to see if the last 9 digits match. That will eliminate all but a tiny percentage of random numbers. Or, for an even faster but slightly weaker filter, using 64-bit arithmetic check that the last 20 digits are divisible by 220 and not by 10.
Here is an easy probabilistic solution.
Say your number is n, and we want to find k: n = 2^k. Obviously, k = log2(n) = log10(n) * log2(10). We can estimate log10(n) ~ len(n) and find k' = len(n) * log2(10) with a small error (say, |k - k'| <= 5, I didn't check but this should be enough). Probably you'll need this part in any solutions that can come in mind, it was mentioned in other answers as well.
Now let's check that n = 2^k for some known k. Select a random prime number P with from 2 to k^2. If remainders are not equal that k is definitely not a match. But what if they are equal? I claim that false positive rate is bounded by 2 log(k)/k.
Why it is so? Because if n = 2^k (mod P) then P divides D = n-2^k. The number D has length about k (because n and 2^k has similar magnitude due to the first part) and thus cannot have more than k distinct prime divisors. There are around k^2 / log(k^2) primes less than k^2, so a probability that you've picked a prime divisor of D at random is less than k / (k^2 / log(k^2)) = 2 log(k) / k.
In practice, primes up to 10^9 (or even up to log(n)) should suffice, but you have to do a bit deeper analysis to prove the probability.
This solution does not require any long arithmetics at all, all calculations could be made in 64-bit integers.
P.S. In order to select a random prime from 1 to T you may use the following logic: select a random number from 1 to T and increment it by one until it is prime. In this case the distribution on primes is not uniform and the former analysis is not completely correct, but it can be adapted to such kind of random as well.
i am not sure if its easy to apply, but i would do it in the following way:
1) show the number in binary. now if the number is a power of two, it would look like:
1000000....
with only one 1 and the rest are 0. checking this number would be easy. now the question is how is the number stored. for example, it could have leading zeroes that will harden the search for the 1:
...000010000....
if there are only small number of leading zeroes, just search from left to right. if the number of zeroes is unknown, we will have to...
2) binary search for the 1:
2a) cut in the middle.
2b) if both or neither of them are 0 (hopefully you can check if a number is zero in reasonable time), stop and return false. (false = not power of 2)
else continue with the non-zero part.
stop if the non-zero part = 1 and return true.
estimation: if the number is n digits (decimal), then its 2^n digits binary.
binary search takes O(log t), and since t = 2^n, log t = n. therefore the algorithm should take O(n).
assumptions:
1) you can access the binary view of the number.
2) you can compare a number to zero in a reasonable time.

Find n fibonacci numbers after a given number

Is there a way to find n fibonacci numbers starting from a given k?
I know that the basic method would be to find all fibonacci numbers starting from 0, keep track of when a number in the series is greater than k, and then find n numbers from that point. But is there a simpler way?
What if I want to find only 3 fibonacci numbers after 5,000,000? Do I have to find all the numbers in the series starting from 0?
Also, if the only way to solve this would be to start from 0, then which approach would be better? The iterative or the recursive one?
Thanks.
Using the golden ratio you can calculate Nth fibonacci.
phi = 1.61803...
Xn=(phi^n - (1-phi)^n) / sqrt(5)
Where n starts with 0.
http://en.wikipedia.org/wiki/Golden_ratio#Relationship_to_Fibonacci_sequence
This formula gives you the position of the number related to the next and previous Fibonacci number. That is, if the formula yields a natural number, it is the Nth Fibonacci number. If yields a number with decimals it belongs between the previous and next natural number. If the number is 2.7, it is between 2 and 3, so you are looking for fib(3), fib(4) and fib(5)
Or you can use Gessel formula.
A number is a Fibonacci if and only if
5*n^2+4 is a square number or 5*n^2-4 is a square number
So you could start counting from your ``N (in this example 5*10^6) until you hit the two first Fibonacci.
The fibonacci sequence grows exponentially, which means you don't have to do very many iterations before you're above 5 million. In fact, the 37th Fibonacci number is above 5 million.
So I wouldn't look further than naive iteration, here in Python:
def fib(a0, k):
a, b = 0, 1
while a < a0:
a, b = b, a + b
for _ in xrange(k):
yield a
a, b = b, a + b
print list(fib(5000000, 3))
You might want to check this out
http://www.maths.surrey.ac.uk/hosted-sites/R.Knott/Fibonacci/fibFormula.html
although I don't think it is worthy to use for big input of N, this method uses the binet's formula.

Resources