This book aims to be an accessible introduction into the design and analysis of efficient algorithms. Throughout the book we will introduce only the most basic techniques and describe the rigorous mathematical methods needed to analyze them.

The topics covered include:

The divide and conquer technique.

The use of randomization in algorithms.

The general, but typically inefficient, backtracking technique.

Dynamic programming as an efficient optimization for some backtracking algorithms.

Greedy algorithms as an optimization of other kinds of backtracking algorithms.

Hill-climbing techniques, including network flow.

The goal of the book is to show you how you can methodically apply different techniques to your own algorithms to make them more efficient. While this book mostly highlights general techniques, some well-known algorithms are also looked at in depth. This book is written so it can be read from "cover to cover" in the length of a semester, where sections marked with a * may be skipped.