Everyone says the same thing: "a real programmer knows how to handle real problems." But they forget how they learned this ability or where: it's not taught in schools.

  1. What can I do to improve my ability to tackle complex programming problems?
  2. What strategies have worked for you?
  3. Are there specific areas I should be focusing on, like algorithms or design patterns?

it's not taught in schools

That's where I got taught.

  1. Practice, practice, practice.
  2. In school we were taught flowcharts, DFD's, waterfall development, UML, etc. These all help you look at a problem from different angles. Although I hardly use any of them, they all influence how you look at a problem.
  3. Algorithms yes, design patterns are for later IMO. There are a lot of common algorithms (sorting for example) which all appear in real problems.

it's not taught in schools.

It depends on the school. Generally I question schools that don't teach Math-based Computer Science, but I'm biased.

What can I do to improve my ability to tackle complex programming problems?

You can try project euler. It was taken down recently, but you can still verify your answers with the power of google. Just don't cheat. You can also try Rosalind Bioinformatics Stronghold. These may not give you practice learning the funamental algo's, but it certianly challenges you in terms of problem solving.

Another suggestion: Start a github account. If you need a program, and you're unable to find a good one, or if you think you can do it better, then go ahead and do it. These will pile up quickly. Also, if you don't know how to use revision control, now will be a good time to learn (it's an essential tool). This will give you more practical expeirence.

Are there specific areas I should be focusing on, like algorithms or design patterns?

First you should be very familiar with implmenting all of the normal algorithms and data structures. Again, here are a few notes from someone else in my school. For example, what kind of structure would you use for fast 2d collision detection (which is used in most games)? If you expect the distribution of object to be even, what would you choose? What if you expected them to cluster togeather? Once your familiar with basic data structures and algo's, you should have a few choices popping into your head.

Consider the classic n-queens problem:
Place n Queens on an nxn chessboard such that no 2 Queens are attacking eachother.

What algorithm would you use to quickly generate all of the possible solutions? What algorithm would you use to quickly generate ONE solution? Again, there are a few "fundamental" algorithms for both.

commented: thankyou +0

Problem solving skills is a combination of many things, and that's why it's difficult to pin down as one particular thing you need to learn.

There is definitely an analytical aspect to problem solving, which is sort of what Hiroshe is hinting at. This is the ability to extract, from a problem definition, the essential aspects of it and frame it in an appropriate way in your mind. This is where classical computer science knowledge is useful, i.e., knowing all those classic algorithms and kinds of problems (e.g., TSP, clustering, sorting, etc..) and how to analyse them.

But another major part of having problem solving skills is having a large bag of practical tricks or patterns. Because the reality is, most programming tasks don't involve you sitting down and "analysing" the problem at hand, they involve you pulling the appropriate trick out of your bag of tricks and apply it to the problem. In other words, it's mostly about "ah, this is this kind of a problem, I have a trick for that, here it is..". At first, as a programmer, you might find yourself analysing every problem to come up with the best solution for it, and then, it gradually transitions to having a bag of tricks big enough to quickly solve almost any day-to-day programming problem. And this is something you can only learn through experience and practice.

Yet another aspect of problems solving skills is the ability to anticipate road-blocks or "theory meets reality" issues. This is kind of the "lessons learned" aspect of problem solving. Sometimes, especially early on, you come up with "smart" solutions to problems (that work great on paper) just to find yourself stuck in a ditch some time later down the road, or finding out that the solution does not live up to its expectations because of things you didn't consider in your analysis (a very typical example is thrashing cache memory). This is, again, something that you gain with experience, but you need to have the analytical skills to be able to learn from those mistakes and incorporate those lessons into your analysis, which can be difficult if you don't have strong analytical skills.

Studying algorithms and data structures are great for learning to develop the analytical skills to solve complex programming problems. But I would say that the most common things you encounter in real life are simple programming problems and complex software architecture problems. Design patterns help with the latter, but beware that learning design patterns without the benefit of experience often leads nowhere, because you cannot understand the motivations behind those patterns until you've experienced those issues yourself. For example, how can you really understand the benefit of the "compilation firewall" pattern if you've never had to deal with the maintenance of a large library with many dependencies. I remember that early on in my programming "career", I didn't really understand any of these design patterns (I understood the "how" but not the "why", which is the one that matters), or I didn't care to, but later on, upon a second look, and with a few more years of experience, they were a gold mine of wise guidelines and practical ways to avoid pitfalls.

I would say that the main thing you need to do to develop your problem solving skills is to head out on unpaved roads. Manufactured problems from textbooks or tutorial sites are just there to flex a few analytical muscles to make you feel good, like training in a gym. But to learn to survive in the wild, you need to go there. Just like having built up muscle and fitness in a gym cannot hurt when it comes to surviving in the wild, it's not going to save you either. Take on a complete, complicated, real-life problem and build up the software for it from the ground up, and be prepared to fail completely a few times (and start over) before you're through with it.

commented: thankyou +0

And problem solving skills only work when the problem is defined. A well defined problem is 50% solved or more IMHO.

problem solving is about the only thing you realistically learn in school.
Unless of course you don't put in any effort whatsoever and just mindlessly cram for your tests.