This course is about the design and analysis of algorithms. The student learns some basic mathematical tools that allow him to give an estimate of the running time of an algorithm without actually implementing it. We mainly describe three programming strategies that help us solve a problem more efficiently: greedy, divide- and-conquer, and dynamic programming. Several important problems that are interesting from a practical and theoretical point of views will be analyzed, including some of the very well-known NP-complete problems. Prerequisite: CSC 313.