These two books below are two books I greatly enjoyed reading and helped me a lot in gaining a firmer grip on algorithms. They are pretty well known, especially the second one, but I thought I would drop my two cents too. Cheers.
Algorithm Design (by Jon Kleinberg and Eva Tardos) – A great read for newcomers and more knowledgeable readers alike.
The first three chapters introduce the basic concepts of algorithm design and graphs, getting an inexperienced reader up to date with the knowledge required for the more advanced stuff later on. Those advanced design concepts are explained in simple terms (except a few sections here and there that get bogged down in math and notation) that everyone can follow without much hassle.
The main algorithmic techniques are presented in chapters 4 to 7 (Greedy Algorithms, Divide and Conquer, Dynamic Programming and Network Flow). Those chapters offer very intuitive introductions to the subjects, and as they progress, they take on bigger challenges that are still presented in a neat way. Another cool feature is the tie-in with real problems. The reader not only reads about the theory, but is also shown how to solve algorithmic problems. The methodology presented in those chapters can be easily used to solve a wide range of problems.
The greatest plus of the book is the solved exercises it presents. At the end of every chapter it offers detailed solutions to problems, so the reader can really understand how to go about solving problems on their own. On top of that, the unsolved exercises come in varied difficulties, from tame to very challenging.
All in all, I highly suggest this book to aspiring Computer Scientists.
Introduction to Algorithms (by Cormer, Leiserson, Rivest, Stein) – I highly recommend this book. It offers a very thorough and clean introduction to the basics of algorithm design, while also going very in depth in later chapters. It also includes an Appendix for Math stuff, which has come in handy many times I need a refresh in memory.
The book has some math heavy chapters, but mostly the math you’ll find are easily digestible. The last chapter presents a wide range of topics, from Linear Programming to String Matching. A particularly good read is the Approximation Algorithms, which presents some very interesting concepts and problems. There is also a chapter for Graph Algorithms where the authors go in depth on some of the most well known graph algorithms. Very interesting read that helps get a better feel of how the algorithms work. There is also a chapter for Advanced Data Structures, which offers a very detailed view of some of the lesser known structures, like Fibonacci Heaps. Also a very interesting read, although it does become a bit hard to follow at times.
One big plus for this book is the exercises at the end of every chapter. Even though they do not have any solutions (although you can easily find them online), they are very interesting and also very helpful in understanding the concepts presented in the chapter.
This is a book every Computer Scientist should have in his collection.