Pay very dose attention to any information in the problem description. You will need it all for an optimal solution. If you have documentation on the domain subject, read it. If you have technical documentation around the problem, read it. Your focus at this point is to get as much knowledge as possible around the problem.

Make sure to have examples of the problem so that you can verify that the problem exists. For example, let’s say your problem is that a payment amount is not calculated correctly based on some logic, make sure you have the fields and values that make the payment amount incorrectly. Check that case and other cases that you may see as a problem.

Get a brute-force solution as soon as possible. Don’t worry about developing an efficient algorithm yet. State a naive algorithm and its runtime, then optimize from there.

Walk through your brute-force solution and optimize areas that can be optimized. Look at time complexity. Make a time vs. space trade off if possible. Hash tables are very useful in this situation. Many times you can solve it manually on paper, then reverse engineer your thought process.

Now that you have your optimal solution, walk through your approach with details. Make sure you understand your optimal solution in your head.

Now that you have your solution on paper, it’s time to make it work in code. Modularize your code from the beginning and refactor to clean up anything that isn’t clear.

Write tests, write tests and write some more tests. You must write tests to support and verify your solution. Having tests that verify your solution will hold your solution stable and last long.

- Unit tests
- Integration tests
- Functional tests
- UI tests

Walk through your code like you would for a detailed code review. Remember that small test cases are much faster and just as effective as big test cases.

Cover special cases and edge cases.