I like solving algorithm problems on TopCoder site. I can implement most of the basic recursive problems such as backtracking, dfs… However, whenever I encounter a complex recursion, it often takes me hours and hours. And when I check the solution of other coders, I feel so shame on myself. I’ve been programming for almost 5 years. I can see the significant improvement on other programming technique such as manipulating string, graphics, GUI … but not recursion? Can anyone share some experiences how to approach a recursive problems? Thanks!
Update
I’m familiar with Unit-Test methodology. Even before I knew Unit Test, I often write some small test functions to see if the result is what I want. When facing recursive problems, I lost this ability naturally. I can insert several “cout” statements to see the current result, but when the call is nested deeply, I no longer can keep track of it. So most of the time, either I solved it using pencil and paper first or I’m done ( can’t use regular method like breaking it into smaller pieces ). I feel like recursion has to work as a whole.
Best regards,
Chan
This is a very good question.
The best answer I have is factoring: divide and conquer. This is a bit tricky in C++ because it doesn’t support higher order functions well, but you can do it. The most common routines are things like maps and folds. [C++ already has a cofold called std::accumulate].
The other thing you have to consider carefully is how to structure your code to provide tail recursion where possible. One soon gets to recognize tail calls and think of them as loops, and this reduces the brain overload from recursing everywhere quite a bit.
Another good technique is called trust. What this means is, you write a call to a function you may not even have defined yet, and you trust that it will do what you want without further ado. For example you trust it will visit the nodes of a tree bottom up correctly, even if it has to call the function you’re currently writing. Write comments stating what the pre- and post-conditions are.
The other way to do this (and I’m sorry about this) is to use a real programming language like Ocaml or Haskell first, then try to translate the nice clean code into C++. This way you can see the structure more easily without getting bogged down with housekeeping details, ugly syntax, lack of localisation, and other stuff. Once you have it right you can translate it to C++ mechanically. (Or you can use Felix to translate it for you)
The reason I said I’m sorry is .. if you do this you won’t want to write C++ much anymore, which will make it hard to find a satisfying job. Example, in Ocaml, just add elements of a list (without using a fold):
This isn’t tail recursive, but this is:
The transformation above is well known. The second routine is actually simpler when you understand what it is doing. I’m too lazy to translate this into C++, perhaps you can transcode it.. (the structure of the algorithms alone should be enough to figure out the syntax)