Problem solving is an essential part of every scientific discipline. It has two components: (1) problem identification and formulation, and (2) the solution to the formulated problem. One can solve a problem on its own using ad hoc techniques or by following techniques that have produced efficient solutions to similar problems. This required the understanding of various algorithm design techniques, how and when to use them to formulate solutions, and the context appropriate for each of them. This book presents a design thinking approach to problem solving in computing — by first using algorithmic analysis to study the specifications of the problem, before mapping the problem on to data structures, then on to the situatable algorithms. Each technique or strategy is covered in its own chapter supported by numerous examples of problems and their algorithms. The new edition includes a comprehensive chapter on parallel algorithms, and many enhancements.