How to find nth Fibonacci number using Javascript with O(n) complexity - javascript

Trying really hard to figure out how to solve this problem. The problem being finding nth number of Fibonacci with O(n) complexity using javascript.
I found a lot of great articles how to solve this using C++ or Python, but every time I try to implement the same logic I end up in a Maximum call stack size exceeded.
Example code in Python
MAX = 1000
# Create an array for memoization
f = [0] * MAX
# Returns n'th fuibonacci number using table f[]
def fib(n) :
# Base cases
if (n == 0) :
return 0
if (n == 1 or n == 2) :
f[n] = 1
return (f[n])
# If fib(n) is already computed
if (f[n]) :
return f[n]
if( n & 1) :
k = (n + 1) // 2
else :
k = n // 2
# Applyting above formula [Note value n&1 is 1
# if n is odd, else 0.
if((n & 1) ) :
f[n] = (fib(k) * fib(k) + fib(k-1) * fib(k-1))
else :
f[n] = (2*fib(k-1) + fib(k))*fib(k)
return f[n]
// # Driver code
// n = 9
// print(fib(n))
Then trying to port this to Javascript
const MAX = 1000;
let f = Array(MAX).fill(0);
let k;
const fib = (n) => {
if (n == 0) {
return 0;
}
if (n == 1 || n == 2) {
f[n] = 1;
return f[n]
}
if (f[n]) {
return f[n]
}
if (n & 1) {
k = Math.floor(((n + 1) / 2))
} else {
k = Math.floor(n / 2)
}
if ((n & 1)) {
f[n] = (fib(k) * fib(k) + fib(k-1) * fib(k-1))
} else {
f[n] = (2*fib(k-1) + fib(k))*fib(k)
}
return f[n]
}
console.log(fib(9))
That obviously doesn't work. In Javascript this ends up in an infinite loops. So how would you solve this using Javascript?
Thanks in advance

you can iterate from bottom to top (like tail recursion):
var fib_tail = function(n){
if(n == 0)
return 0;
if(n == 1 || n == 2)
return 1;
var prev_1 = 1, prev_2 = 1, current;
// O(n)
for(var i = 3; i <= n; i++)
{
current = prev_1 + prev_2;
prev_1 = prev_2;
prev_2 = current;
}
return current;
}
console.log(fib_tail(1000))

The problem is related to scope of the k variable. It must be inside of the function:
const fib = (n) => {
let k;
You can find far more good implementations here list
DEMO

fibonacci number in O(n) time and O(1) space complexity:
function fib(n) {
let prev = 0, next =1;
if(n < 0)
throw 'not a valid value';
if(n === prev || n === next)
return n;
while(n >= 2) {
[prev, next] = [next, prev+next];
n--;
}
return next;
}

Just use two variables and a loop that counts down the number provided.
function fib(n){
let [a, b] = [0, 1];
while (--n > 0) {
[a, b] = [b, a+b];
}
return b;
}
console.log(fib(10));

Here's a simpler way to go about it, using either iterative or recursive methods:
function FibSmartRecursive(n, a = 0, b = 1) {
return n > 1 ? FibSmartRecursive(n-1, b, a+b) : a;
}
function FibIterative(n) {
if (n < 2)
return n;
var a = 0, b = 1, c = 1;
while (--n > 1) {
a = b;
b = c;
c = a + b;
}
return c;
}
function FibMemoization(n, seenIt = {}) {//could use [] as well here
if (n < 2)
return n;
if (seenIt[n])
return seenIt[n];
return seenIt[n] = FibMemoization(n-1, seenIt) + FibMemoization(n-2, seenIt);
}
console.log(FibMemoization(25)); //75025
console.log(FibIterative(25)); //75025
console.log(FibSmartRecursive(25)); //75025

You can solve this problem without recursion using loops, runtime O(n):
function nthFibo(n) {
// Return the n-th number in the Fibonacci Sequence
const fibSeq = [0, 1]
if (n < 3) return seq[n - 1]
let i = 1
while (i < n - 1) {
seq.push(seq[i - 1] + seq[i])
i += 1
}
return seq.slice(-1)[0]
}

// Using Recursion
const fib = (n) => {
if (n <= 2) return 1;
return fib(n - 1) + fib(n - 2);
}
console.log(fib(4)) // 3
console.log(fib(10)) // 55
console.log(fib(28)) // 317811
console.log(fib(35)) // 9227465

Related

prevent an infinite loop in a production system(Js Code Test question)

Please understand the following program:
function recur(n, cur) {
if (!cur) {
cur = 0;
}
if (n < 2) {
throw new Error('Invalid input');
}
if (n === 2) {
return 1 / n + cur;
}
return recur(n - 1, cur + 1 / (n * (n - 1)));
}
To prevent an infinite loop in a production system. Write a program doing the same
calculation without recursion. Please be reminded that a while loop is also considered
not good in a production system.
I don't quite understand what the original CODE is supposed to do :(
here is your function without recursive.
function nonRecur(n, cur) {
if (!cur) {
cur = 0;
}
if (n < 2) {
throw new Error('Invalid input');
}
for (; n > 1; --n){
if (n === 2) {
cur = 1 / n + cur;
break;
}
cur = cur + 1 / (n * (n - 1));
}
return cur
}
you can try below code for the same
function recur(n, cur) {
if (!cur) {
cur = 0;
}
if (n < 2) {
throw new Error('Invalid input');
}
for(var i = n; i > 2; i--){
cur = cur+1/(i * (i -1));
}
return 1 / i + cur;
}
Python solution for this
# Cur default value is 0, if it is not pass.
def recurFunction(n,cur=0):
if n < 2:
# print("Error: Invalid input")
return ValueError("Invalid input")
# Decreasing the value of n by 1 till n become 2
for i in range(n,1,-1):
if i == 2:
return 1/i+cur
else:
cur = cur+1/(i * (i -1))
In python, we can convert this recursion problem into iteration by following snippet. . Also there is a website where you visually check the recursion process Visualise Recursion process. I hope you will find my solution perfect.

Check if it's possible to build a triangle from three parameters (Cognitive Complexity to high)

I can't find a way to code this challenge without either getting too complex or forging a on turn loop. The function receives three integers as parameters. Here follows my code.
function triangleCheck(lineA, lineB, lineC) {
let ar12 = [lineA, lineB, lineC];
if (triangleLineValidation(ar12) === 3 ) {
return true;
} else { return false}
}
function triangleLineValidation(ar12) {
let check = 0;
for (let i = 0; i < ar12.length; i += 1) {
for (let j = i + 1; i < ar12.length; i += 1) {
if (ar12[i] + ar12[j] > ar12[2 - i] && Math.abs(ar12[i] - ar12[j]) < ar12[2 - i]) {
check += 1;
}
}
}
return check;
}
I think the cleanest way to write this is:
const triangleLineValidation = (arr) =>
(arr[0] + arr[1] > arr[2] &&
arr[1] + arr[2] > arr[0] &&
arr[2] + arr[0] > arr[1])
const triangleCheck = (a,b,c) => a+b>c && a+c>b && b+c>a && Math.abs(a-b)<c && Math.abs(a-c)<b && Math.abs(b-c)<a;
#Thomas I've tried this approach, but it also has Cognitive Complexity issues, since the code is being repeated many times, I guess
then let's break it down:
const checkSide = (a,b,c) => a + b > c && Math.abs(a - b) < c;
const triangleCheck = (a,b,c) => checkSide(a,b,c) && checkSide(b,c,a) && checkSide(c,a,b);
or
function triangleCheck(a, b, c) {
return [a, b, c].every(triangleLineValidation);
}
function triangleLineValidation(c, i, array) {
const a = array[(i + 1) % array.length];
const b = array[(i + 2) % array.length];
return a + b > c && Math.abs(a - b) < c;
}
never dealt with a computer having "Cognitive Complexity issues" with my code, so I'm not quite sure how to properly dumb it down.

Get binary representation of integer

I just had an interview question, where I need to get the binary representation of an integer, this is something I should know how to do.. for example, 5 is represented in binary as 101, and the steps look something like:
// 5 % 2 = 1
// 5 / 2 = 2
// result = 1;
// 2 % 2 = 0
// 2 / 2 = 1
// result = 10
// 1 % 2 = 1
// 1 / 2 = 0
// result = 101
the stopping condition is when ~~(1/2) === 0
so I have this:
const getBinary = (v) => {
let remainder, binary = 1;
while (true) {
remainder = v % 2;
v = ~~(v / 2);
if (v === 0) {
return binary;
}
if (remainder === 0) {
binary = binary * 10 + 1;
}
else {
binary = binary * 10;
}
}
};
console.log(getBinary(5));
so that works, but the binary variable is initialized to 1. Is there a way to improve this so it works with negative numbers, or if 0 is passed as the argument to the function?
var integer = 52;
console.log(integer.toString(2));
Simple function native to javascript, no lengthy code required.
If you want to write it from scratch you can use something like this:
function toBinary(n) {
n = Number(n);
if (n == 0) return '0';
var r = '';
while (n != 0) {
r = ((n&1)?'1':'0') + r;
n = n >>> 1;
}
return r;
}
console.log(toBinary(5));
console.log(toBinary(10));
console.log(toBinary(-5));
console.log(toBinary(0));
So here is one way. It has an inner function that handles the basics and an outer one that extends to your special cases. I preferred to do string representations.
const getBinary = v => {
if (v === 0) return '';
let remainder = v % 2;
let quotient = (v - remainder) / 2;
if (remainder === 0) {
return getBinary(quotient) + '0';
}
else {
return getBinary(quotient) + '1';
}
}
const betterGetBinary = v => {
if (v === 0) return '0';
if (v < 0) return '-' + getBinary(-v);
return getBinary(v);
}
console.log(betterGetBinary(-10));
A quick and dirty solution, although it 'might' have two flaws:
- Math.floor()
- no bitwise operator
let getBinary = number => {
let done = false;
let resultInverted = [];
let acc = number;
while (!done) {
let reminder = acc % 2;
if (acc === 1) {
done = true;
}
acc = Math.floor(acc / 2);
resultInverted.push(reminder);
}
return Number(resultInverted.reverse().join(''));
};
console.log(typeof getBinary(2));
console.log(getBinary(5));
console.log(getBinary(127));

How to convert this O(n^2) algorithm to O(n)?

https://www.codewars.com/kata/is-my-friend-cheating/train/javascript
My goal is to devise a function that finds number pairs (a, b) which satisfy the equation a * b == sum(1, 2, 3 ..., n-2, n-1, n) - a - b.
The following code finds all the pairs, but is too slow and times out. I have seen in the comments for this challenge that the algorithm needs to have O(n) complexity to pass. How is this done?
function removeNb (n) {
if(n===1) return null;
let sum = (n * (n+1))/2;
let retArr = [];
let a = n;
while( a !== 0){
let b = n;
while( b !== 0){
if(b != a && a*b == ((sum - b) - a) ){
retArr.push([a,b]);
}
b--;
}
a--;
}
retArr.sort( (a,b) => a[0] - b[0]);
return retArr;
}
Thanks to all for the assistance! Here is my final solution:
function removeNb (n) {
let retArr = [];
let a = 1;
let b = 0;
let sumN = (n * (n+1))/2;
while( a <= n){
b = parseInt((sumN - a) / (a + 1));
if( b < n && a*b == ((sumN - b) - a) )
retArr.push([a,b]);
a++;
}
return retArr;
}
I think my main issue was an (embarrassing) error with my algebra when I attempted to solve for b. Here are the proper steps for anyone wondering:
a*b = sum(1 to n) - a - b
ab + b = sumN - a
b(a + 1) = sumN - a
b = (sumN - a) / (a + 1)
You can solve for b and get: b = (sum - a)/(a + 1) (given a != -1)
Now iterate over a once -> O(n)
let n = 100;
let sumOfNum = n => {
return (n * (n + 1)) / 2;
};
let sum = sumOfNum(n);
let response = [];
for (let i = 1; i <= 26; i++) {
let s = (sum - i) / (i + 1);
if (s % 1 == 0 && s * i == sum - s - i && s <= n) {
response.push([s, i]);
}
}
// this is O(N) time complexity
Here's an implementation:
function removeNb(n){
var sum = (1 + n) * n / 2;
var candidates = [];
// O(n)
for(var y = n; y >= 1; y--){
x = (-y + sum) / (y + 1);
/*
* Since there are infinite real solutions,
* we only record the integer solutions that
* are 1 <= x <= n.
*/
if(x % 1 == 0 && 1 <= x && x <= n)
// Assuming .push is O(1)
candidates.push([x, y]);
}
// Output is guaranteed to be sorted because
// y is iterated from large to small.
return candidates;
}
console.log(removeNb(26));
console.log(removeNb(100));
https://jsfiddle.net/DerekL/anx2ox49/
From your question, it also states that
Within that sequence, he chooses two numbers, a and b.
However it does not mention that a and b are unique numbers, so a check is not included in the code.
As explained in other answers, it is possible to make a O(n) algorithm solving for b. Moreover, given the symmetry of solution -- if (a,b) is a solution, also (b,a) is -- it is also possible to save some iterations adding a couple of solutions at a time. To know how many iterations are required, let us note that b > a if and only if a < -1+sqrt(1+sum). To prove it:
(sum-a)/(a+1) > a ; sum-a > a^2+a ; sum > a^2+2a ; a^2+2a-sum < 0 ; a_1 < a < a_2
where a_1 and a_2 comes from 2-degree equation solution:
a_1 = -1-sqrt(1+sum) ; a_2 = -1+sqrt(1+sum)
Since a_1 < 0 and a > 0, finally we proved that b > a if and only if a < a_2.
Therefore we can avoid iterations after -1+sqrt(1+sum).
A working example:
function removeNb (n) {
if(n===1) return null;
let sum = (n * (n+1))/2;
let retArr = [];
for(let a=1;a<Math.round(Math.sqrt(1+sum));++a) {
if((sum-a)%(a+1)===0) {
let b=(sum-a)/(a+1);
if(a!==b && b<=n) retArr.push([a,b],[b,a]);
}
}
retArr.sort( (a,b) => a[0] - b[0]);
return retArr;
}
However, with this implementation we still need the final sort. To avoid it, we can note that b=(sum-a)/(a+1) is a decreasing function of a (derive it to prove). Therefore we can build retArr concatenating two arrays, one adding elements to the end (push), one adding elements at the beginning (unshift). A working example follows:
function removeNb (n) {
if(n===1) return null;
let sum = (n * (n+1))/2;
let retArr = [];
let retArr2 = [];
for(let a=1;a<Math.round(Math.sqrt(1+sum));++a) {
if((sum-a)%(a+1)===0) {
let b=(sum-a)/(a+1);
if(a!==b && b<=n) {
retArr.push([a,b]);
retArr2.unshift([b,a]); // b>a and b decreases with a
}
}
}
retArr=retArr.concat(retArr2); // the final array is ordered in the 1st component
return retArr;
}
As a non-native speaker, I would say that the phrase from the reference "all (a, b) which are the possible removed numbers in the sequence 1 to n" implies a!=b,
so I added this constraint.

Most efficient way to calculate Fibonacci sequence in Javascript

I'm attempting to get better with optimizing algorithms and understanding big-o, etc.
I threw together the below function to calculate the n-th Fibonacci number. This works (for a reasonably high input). My question is, how can I improve this function? What are the drawbacks of calculating the Fibonacci sequence this way?
function fibo(n) {
var i;
var resultsArray = [];
for (i = 0; i <= n; i++) {
if (i === 0) {
resultsArray.push(0);
} else if (i === 1) {
resultsArray.push(1);
} else {
resultsArray.push(resultsArray[i - 2] + resultsArray[i - 1]);
}
}
return resultsArray[n];
}
I believe my big-o for time is O(n), but my big-o for space is O(n^2) due to the array I created. Is this correct?
If you don't have an Array then you save on memory and .push calls
function fib(n) {
var a = 0, b = 1, c;
if (n < 3) {
if (n < 0) return fib(-n);
if (n === 0) return 0;
return 1;
}
while (--n)
c = a + b, a = b, b = c;
return c;
}
Performance Fibonacci:
var memo = {};
var countInteration = 0;
var fib = function (n) {
if (memo.hasOwnProperty(n)) {
return memo[n];
}
countInteration++;
console.log("Interation = " + n);
if (n == 1 || n == 2) {
result = 1;
} else {
result = fib(n - 1) + fib(n - 2);
}
memo[n] = result;
return result;
}
//output `countInteration` = parameter `n`

Categories

Resources