Understanding Recursion

不吃貓的魚發表於2018-11-11

Recursion, simply put, is calling a function on itself. It can used to break down complex problems into smaller manageable similar units that can be handled by the same function.

Recursion vs Iteration

An iterative function is one that loops to repeat some part of the code, and a recursive function is one that calls itself again to repeat the code.

E.g To calculate the sum of an array of numbers

function iterativeSum(arr) {
    let sum = 0;
    for (let i of arr) {
        sum += i;
    }
    return sum;
}


function recursiveSum(arr) {
    if (arr.length === 0) {
        return 0;
    }
    return arr[0] + recursiveSum(arr.slice(1));
}

/**
 *
 * iterativeSum([1,2,3]) => 1 + 2 + 3 => 6
 *
 * recursiveSum([1,2,3])
 *     => 1 + recursiveSum([2,3])
 *     =>       2 + recursiveSum([3])
 *     =>           3 + recursiveSum([])
 *     =>               0
 *     => 0 + 3 + 2 + 1 => 6
 */

console.log(iterativeSum([1,2,3])); //6
console.log(recursiveSum([1,2,3])); //6
複製程式碼

How to use recursion

base condition is a must

Using recursion without a base condition leads to infinite recursion. As recursion is calling the function on itself, base condition indicates when to terminate the process.

function infiniteRecursion() {
    // keeps calling itself without termination
    return infiniteRecursion();
}
複製程式碼

break down the problem into smaller units that can be handled by the function itself.

E.g.

the sum of an array = the value of first element + the sum of the rest of array.

That`s how we do it recursively in recursiveSum example above.

Practices make perfect

Q1

Question:

By starting from the number 1 and repeatedly either adding 5 or multiplying by 3, an infinite amount of new numbers can be produced. Write a function that, given a number, tries to find a sequence of such additions and multiplications that produce that number.

Thoughts:

To find a solution for a number(let`s call it A), we tries adding 5 or multiplying 3 to the current number(let`s call it B) and use recursion to
check if there is a solution for the result(i.e. B + 5 or B * 3). The base condition is when the current number is greater than(boom!) or equal to(solution found!) A.

Solution:

function findSolution(num) {
    function find(start, history) {
        if(start > num) {
            return null; // boom!
        } else if (start === num) {
            return history; //solution found
        }
        return find(start + 5, `(${history} + 5)`) || find(start * 3, `(${history} * 3)`);
    }

    return find(1, `1`);
}

console.log(findSolution(13)); //(((1 * 3) + 5) + 5)
console.log(findSolution(20)); //null
複製程式碼

Q2

  • Question: Inorder(Left, Right, Top) traversal of binary tree

  • Solution

class Node {
    constructor(value, left=null, right=null) {
        this.value = value;
        this.left = left;
        this.right = right;
    }
}

function inorder(node, fn) {
    if(node == null) {
        return;
    }
    inorder(node.left, fn);
    fn(node);
    inorder(node.right, fn);
}

function test() {
    /**
     *        A
     *      /   
     *    B       C
     *   /        
     *  E   F       H 
     */
    let E = new Node(`E`),
        F = new Node(`F`),
        H = new Node(`H`),
        B = new Node(`B`, E, F),
        C = new Node(`C`, null, H),
        A = new Node(`A`, B, C);
    inorder(A, node => console.log(node.value)); // E B F A C H
}
test();
複製程式碼

Reference

Notice

  • If you want to follow the latest news/articles for the series of reading notes, Please 「Watch」to Subscribe.

相關文章