I favor recursive solutions when:
The implementation of the recursion is much simpler than the iterative solution, usually because it exploits a structural aspect of the problem in a way that the iterative approach cannot
I can be reasonably assured that the depth of the recursion will not cause a stack overflow, assuming we're talking about a language that implements recursion this way
Condition 1 doesn't seem to be the case here. The iterative solution is about the same level of complexity, so I'd stick with the iterative route.
Answer from John Feminella on Stack OverflowSo I was watching this video on youtube and was simply amazed by this function to calculate factorials with recursions.
def factorials(n):
if n == 1:
return 1
else:
return n * factorial(n-1)Since I'm pretty new to python and coding in general (I'm a lawyer by profession), I would have solved this problem with loops. The moment I understood the concept of this function, I was baffled by the simplicity and beauty of it.
Now here's my question:
-
In which cases is it smarter to use one or the other and what are the benefits? (if there even is a general rule)
-
Where can I learn more about recursions? Are there any tutorials online?
Thanks :)
python - When to use while loops vs recursion - Stack Overflow
code quality - Recursion or while loops - Software Engineering Stack Exchange
python - What's the difference between nested loops, and recursive functions? - Stack Overflow
Is recursion faster/more efficient than looping?
I favor recursive solutions when:
The implementation of the recursion is much simpler than the iterative solution, usually because it exploits a structural aspect of the problem in a way that the iterative approach cannot
I can be reasonably assured that the depth of the recursion will not cause a stack overflow, assuming we're talking about a language that implements recursion this way
Condition 1 doesn't seem to be the case here. The iterative solution is about the same level of complexity, so I'd stick with the iterative route.
If performance matters, then benchmark both and choose on a rational basis. If not, then choose based on complexity, with concern for possible stack overflow.
There is a guideline from the classic book The Elements of Programming Style (by Kernighan and Plauger) that algorithm should follow data structure. That is, recursive structures are often processed more clearly with recursive algorithms.
You are actually right, the logic behind is the same and you can also apply while loop for e.g. Fibonacci sequence. Just the notation of recursion is usually shorter and more elegant.
Your code can be even simplified a bit and then you see that your solutions are kind of similar:
While loop:
def countdown(n):
while n > 0: # Step 1 -> check
print(n)
n = n-1 # Step 2 -> recursive call in while loop
print('Blast off!') # Step 3 -> end ensured by Step 1
Recursion:
def countdown(n):
if n > 0: # Step 1 -> check
print(n)
return countdown(n-1) # Step 2 -> recursive call of the countdown()
else:
print('Blast off!') # Step 3 -> end ensured by Step 1
Significant is that action n-1. You recursively act on a variable or object (Step 2) as long as your condition related to that variable/object is valid (Step 1).
They are fundamentally different. The way you have described them, both are the same thing as for loops. (I don't mean to be rude) While is used when you want something to happen as long as or until something else happens. Recursion is used for functions that are based on themselves. (common examples being factorial or the Fibonacci sequence) Often, they behave similarly in the manner you described on small scale problems. When scaled up however, both have their advantages and drawbacks.
TLDR: the functions are inherently different in how they iterate. While they each iterate, they do so based on different conditions and with different use cases.
Recursion is not intrinsically better or worse than loops - each has advantages and disadvantages, and those even depend on the programming language (and implementation).
Technically, iterative loops fit typical computer systems better at the hardware level: at the machine code level, a loop is just a test and a conditional jump, whereas recursion (implemented naively) involves pushing a stack frame, jumping, returning, and popping back from the stack. OTOH, many cases of recursion (especially those that are trivially equivalent to iterative loops) can be written so that the stack push / pop can be avoided; this is possible when the recursive function call is the last thing that happens in the function body before returning, and it's commonly known as a tail call optimization (or tail recursion optimization). A properly tail-call-optimized recursive function is mostly equivalent to an iterative loop at the machine code level.
Another consideration is that iterative loops require destructive state updates, which makes them incompatible with pure (side-effect free) language semantics. This is the reason why pure languages like Haskell do not have loop constructs at all, and many other functional-programming languages either lack them completely or avoid them as much as possible.
The reason why these questions appear so much in interviews, though, is because in order to answer them, you need a thorough understanding of many vital programming concepts - variables, function calls, scope, and of course loops and recursion -, and you have to bring the mental flexibility to the table that allows you to approach a problem from two radically different angles, and move between different manifestations of the same concept.
Experience and research suggest that there is a line between people who have the ability to understand variables, pointers, and recursion, and those who don't. Almost everything else in programming, including frameworks, APIs, programming languages and their edge cases, can be acquired through studying and experience, but if you are unable to develop an intuition for these three core concepts, you are unfit to be a programmer. Translating a simple iterative loop into a recursive version is about the quickest possible way of filtering out the non-programmers - even a rather inexperienced programmer can usually do it in 15 minutes, and it's a very language-agnostic problem, so the candidate can pick a language of their choice instead of stumbling over idiosyncracies.
If you get a question like this in an interview, that's a good sign: it means the prospective employer is looking for people who can program, not people who have memorized a programming tool's manual.
It depends.
- Some problems are very amenable to recursive solutions e.g. quicksort
- Some languages don't really support recursion e.g. early FORTRANs
- Some languages assume recursion as a primary means for looping e.g. Haskell
It's also worth noting that support for tail recursion makes tail recursive and iterative loops equivalent, that is, recursion doesn't always have to waste the stack.
Also, a recursive algorithm can always be implemented iteratively by using an explicit stack.
Finally, I'd note that a five-line solution is probably always better than a 100 line one (assuming they are actually equivalent).
A recursive algorithm calls a function from within that same function (recursion). Whether to perform the recursion is based on some condition.
function foo()
{
?/ do work
if( condition )
foo();
}
An iterative algorithm typically calls a function some number of times (n).
function foo()
{}
for(int i = 0; i < n; i++)
foo();
A recursive function is typically used when some piece of data needs to be manipulated repeatedly and the condition of whether to repeat is dependent on the previous manipulation. Computing a truncated infinite series in math is an example of this.
An iterative function is typically used when the condition is not dependent on the previous manipulation. Inverting a matrix has a predefined n.
Either method can be used for most purposes, but you will typically find that one is easier than the other for a particular case.
Be aware of callstack overflow with recursion though. It is best to only use it if you can guarantee that the algorithm will converge and end within some number of recursions.
Recursion can be seen as "just" another way of doing loops. The main advantage is code readability, as you can see in this Stackoverflow question, in this case when there are a lot of nested loops.
Be careful however, as there is a small recursion limit on Python (1000). You can verify by typing
>>>import sys
>>>print sys.getrecursionlimit()
1000
For an overview of other cases of recursion vs loops, check out this pdf. However, as stated in this Stackoverflow answer, you should stick to a purely iterative scheme on Python.
Just curious. I'm doing the chapter 3 practice from Automate the boring stuff, and my first instinct was to use recursion on the collatz function. I initially had trouble and just made a loop, but I was annoyed and went back and did it with recursion too.
I'm wondering though, which way is more efficient? How do I check? I'm assuming recursion is the better of the two, but is there a way to check?
code with recursion
code with loop and no recursion