This is an introductory-level course in computational complexity theory, which is one of the core areas in theoretical computer science. Motivated by questions such as the P vs NP problem, the goal of complexity theory is to explore the limits of efficient computation: Which problems are inherently hard to solve, and what makes them so? How do resource constraints (such as limited time and memory) inhibit algorithms, and why? And which mathematical and algorithmic tools can we use to study these questions? The purpose of the course is to introduce graduate students to the fundamental notions and results in the area, as well as expose students to active lines of research.