Algorithm Design


How to think of a recursive solution?

What is recursion?


When to use recursion?


Why recursion? Why not? two common reasons for using recursion:

Recursion can lead to stack overflow errors. downside of recursion is that it may take more space than an iterative solution. Building up a stack of recursive calls consumes memory temporarily, and the stack is limited in size, which may become a limit on the size of the problem that your recursive implementation can solve.


How to build a recursive solutions?

Selecting an easier problem (whose solution is given by the orracle)



Analyse correctness and performance


Common Pitfalls

References for Recursion:

Practice Problems:


What is tail recursion?

What are the benefits of tail recursion?

How to convert a recursive solution to an iterative solution?

Recursive function execution flow can be represented as a tree. A recursive logic can be executive by a loop, which uses a data-structure to traverse the recursive tree. Depth-first traversal can be done using a stack, breadth-first traversal can be done using a queue. Thus, you can convert any recursive function into an iterative function by adding a stack; that’s how computers generally implement recursion.

The stack is used to store the work you can’t do right away. For example, the main reason for having a call stack to store information about the active subroutines of a computer program is to keep track of the point to which each active subroutine should return control when it finishes executing. An active subroutine is one that has been called but is yet to complete execution after which control should be handed back to the point of call. Such activations of subroutines may be nested to any level (recursive as a special case), hence the stack structure.

The preorder case is easiest, because there’s only one kind work you have to defer – processing a child node.The stack has to store nodes to visit and nodes to process, but a node to process is always the right child of a node just visited,

Each time a recursive call is made in the algorithm, push the necessary information onto your stack. ii) When you complete processing at this deeper level, pop the simulated stack frame and continue processing in the higher level at the point dictated by the return address popped from the stack. iii) Use an iterative control structure that loops until there are no return addresses left to pop from the stack.

We can convert any recursive function to tail recursive function with continuation (by construct the closure for continuation lambda function) (But here we still have to spend some memory to construct closures)

Are tail recursion and iteration the same?

Any tail recursive function can be made into a loop (example: Word Wrap)

Tail recursion is different from iteration. They’re the same in terms of what the machine is doing, assuming your compiler does tail-call optimization: The difference between tail recursion and iteration is whether or not the target of a jump happens to be the start of a function or not.

But that’s not the same as being “the same” - they present a very different abstraction to the programmer. In a sane language, you expect an error to give you a stack trace of functions that have been called. If you treat recursion as iteration, then either you’ll have to omit some function calls from the stack, or your algorithm won’t work in constant space anymore. Either violates some expectations of the programmer.

References:


How to think of an iterative solution?

What is an iterative function?

How to build an iterative solution?


How to verify correctness of an iterative solution?

sum = 0
i = 0
while i < n
    sum = sum + a[i]
    i = i + 1


29 August 2019