Problem Solving Approach
You're faced with a tough challenge. What are the steps you can take to make it solvable? This section will focus on devising a plan or approach to solving such a problem: steps you can take to make it easier.
Objectives
Define what an algorithm is
Devise a plan to solve algorithms
Compare and contrast problem solving patterns like frequency counters, two pointer problems, and divide and conquer
How to Solve a Problem
Here's the basic steps to solving a problem:
Understand the problem
Explore concrete examples
Break it down
Solve/simplify the problem
Look back and refactor
1. Understand the problem
It's tempting, especially in a stressful setting like an interview, to jump straight into solving a problem. However, here's some things you want to do to make sure you understand the problem first:
Try to restate the problem in your own words.
What are the inputs that go into the problem?
What are the outputs that should come from the solution to the problem?
Can the outputs be determined from the inputs? In other words, are the inputs enough information to get the outputs expected?
How should I label the important pieces of data that are part of the problem? Is there key terminology I should create? (Example: parameter names)
2. Explore concrete examples
Benefits of coming up with concrete examples:
Helps you understand the problem better
You can use the examples as sanity checks to check your work; they tell you inputs and expected outputs
Pro tip: In the working world, user stories and unit tests are both cases of concrete examples. They're ways of checking that a given input leads to a certain expected output.
When creating and exploring your concrete examples, you can follow this pattern:
Start with simple examples first
What are the easiest use cases? How do you solve them first?
Progress to more complex examples next
Jump to edge cases
What are some examples of empty inputs?
What are some examples of invalid inputs?
Let's walk through an example together.
3. Break it down
Explicitly write out the steps you need to take during the solution: rough pseudocode.
Benefits:
Forces you to think about the code that you write before you write it; more targeted, effective, and focused
Helps you catch/keep in your radar things you're afraid of facing or misunderstandings that may steer you away from the solution
Example:
Pro tip: If you just start writing thinking you'll figure out the details later, you risk pigeon-holing yourself into whatever code you write. Worst case scenario: you'll end up deleting everything you wrote. Breaking down your solution into clear steps solves for this problem.
4. Solve/simplify the problem
Now that you've broken down the problem, it's time to implement the solution. However, at this stage, if you find that there's small bits you don't really know how to deal with or find challenging, it might make sense to simplify the problem first.
In other words, SOLVE THE PROBLEM. If you can't, SOLVE A SIMPLER PROBLEM!
Solving the problem is not all or nothing. It's dangerous to put all your eggs in one basket and only aim for a 100% solution. It's often much better to at least have something to show for, so it's smart to solve the 90% you know you can do before working on the last 10% you know you'll get stuck on.
The process:
Find the core difficulties
Temporarily ignore those difficulties
Write a simplified solution
Pro tip: Along the way, you'll often gain insight into how to solve the difficulties
Then try to incorporate those difficulties back in if you can
In the example below, we solve 90% of the charCount
problem except how to check if a character is alphanumeric:
With the example, we can then figure out the alphanumeric validation check and simply plug it into the existing code.
5. Look back and refactor
It's tempting to just stop working on your code once you know that it works. Often times this is acceptable too, if you're tight on time and need something in production fast.
However, it's often important to look back at your code to find ways to improve it. Here's some prompting questions:
Can you test the result to tell you if it works?
Is there another way of deriving the result or solving the problem?
There's often more than one way of doing anything!
Can you understand your solution at a glance? How intuitive and legible is it?
Can you reuse this solution to solve other problems?
Finding these connections yields more positive outcomes.
Can you improve the performance of your solution?
Think space complexity and time complexity.
Can you think of other reasons to refactor?
Other reasons include: adhering to company's style guide
How have other people solved this problem?
Getting other people's solutions can teach you a lot about what you can do.
Note: Sometimes this might mean looking at solutions outside your preferred languages!
Last updated