Sketch out your basic data structures on a piece of paper, then just use your finger to trace out how you could do insert, delete, search, etc you can usually tell if something is taking O(lg n), O(n), O(n lg n), etc just by counting the steps you take. After you're comfortable with this, sketch it in your head. You can't forget something that you understand.
The point is that if figuring what out Big O is seems like something you have to memorize to recall quickly, then you very likely don't really understand the underlying data structure/algorithm (and as such you rightfully should do poorly on algorithms interviews). Take the time to make sure you really understand what's going on, and everything else should fall into place.
We evaluate a lot of people coming straight out of school in CS. They don't have much experience in development. Thus, the best way to test if a candidate is smart is to see if he's learned his course material well. We do a lot of heavy algorithms and distributed systems, so we ask that, but it also happens to be what students learn.
Running time and Oh, however, in addition to systems knowledge, is extremely important to creating good software in general. If you can't determine how your software will scale with big data, and you can't understand why efficient code that runs quickly with small operations does so, you simply can't write good software.
I realize a lot of people on HN take offense at these claims because they've written programs without this knowledge and claim they are self taught. The reality, however, is that they aren't good programmers. You don't need a good programmer to write a prototype that works and determines market fit. You do need good programmers to scale your product, add features efficiently, and architect solutions without making a crippling mess of your code.
Edit: I realize the above comment sounds a little condescending. It wasn't meant to be. I have met self taught programmers that are amazing. Most people just don't have the self discipline to fully learn a subject matter (I many times don't). So a lot of "self taught" programmers have only taught themselves 10% of what they need to know and never bother learning the other 90%.
E-mail, at the time, didn't need them - there was no search, no deduplication, no anything but "do a bunch of deterministic, bounded operations very quickly." Sure, some hash tables and plenty of linked lists, but that's about it.
Am I just a big fat outlier there, condemned to cram Skiena before every interview for the rest of my life?
Judging by the fact that you were able to do many deterministic bounded operations quickly, and understand why they were bounded and why they were quick, I get the feeling that you'd do much better at an algorithm interview than you give yourself credit for.
And I'd also cram CLRS before an interview :P I know I'm good at what I do compared to the avg coder, but compared to the average coder at Palantir, I have a long way to go. I'm in no way satisfied with my ability where it is today and its always smart to take a refresher before an interview.
What you said isn't condescending at all. If you are a self taught programmer and you haven't read up and gotten a good handle on big O notation, data structures, and algorithms, do yourself a favor and start.
By your definition, I am currently a "bad programmer" because I do not have fluency in algorithms.
(I will leave the objective truth of this statement as an exercise to the reader; God knows it might be so. However...)
I contend that I am capable of learning new material quickly enough that, if I were suddenly called upon at my job to write code which handles all of the slings and arrows of algorithmic complexity, I would be able to do so with very little friction. To phrase it differently: I (probably) don't know enough to write gorgeous, algorithmically sophisticated code on the first pass, but I know enough to know when it's time for me to hit the books, and where to start.
Obviously, it would take me longer than someone with prior experience in writing such code! If the overarching question is "does algorithmic fluency constitute a dealbreaker when hiring at certain positions", then I suppose the answer depends on how much longer it would take. I can only speculate on the difference in a flagrantly biased manner, as I would egotistically prefer to believe that I ought to be hired in more cases than not. :-)
Or, if we look through the Dunning-Kruger lens, we may conclude that lack of algorithmic fluency always constitutes a dealbreaker at certain positions, because even if the developer in question can learn on the job, he or she will still make errors and oversights with far-reaching implications that are invisible--unknown unknowns--to the algorithmically illiterate. This feels less plausible to me than the simpler consideration that "learning on the job" may simply be an undesirable speed bump.
I don't really have any concrete points or refutations to make; I'm just fascinated by the issue in general and enjoy exploring the possible angles.
(Also I shall likely just cut the Gordian knot and go play with algorithms until it simply isn't an issue anymore. Go figure)
EDIT: Actually, there is a point I forgot to make:
In your edit you wrote, "So a lot of "self taught" programmers have only taught themselves 10% of what they need to know and never bother learning the other 90%." I think this is the crux of the "good/bad" problem: "what they need to know" is very subjective and dependent on context.
I think it's reasonable to assert that there are programmers out there who have long and satisfying careers, but never learned X, or didn't learn it for many years. Who's to say whether they are "good" or "bad"? It's a judgment, and judgments are meaningless without context: "good programmers need to know X" doesn't really say anything, but "programmers need to know X if they want to Y" does.
You certainly went down this road in your comment, but your Y was "You do need good programmers to scale your product, add features efficiently, and architect solutions without making a crippling mess of your code.", and I feel like lack of fluency in algorithms is just not a surefire indicator of bad architecture skills (among the others you listed) as well.
And since actually getting a new person on-board is an expensive process, you aim for criteria that are a bit too stringent, if you can afford it.
There's also the issue that making a bad algorithmic decision at the center of the problem turns scaling into an insanely hard problem, sometimes. It's not so much about learning about it when you need it, but about avoiding issues in the first place.
True, there are many places where it truly doesn't matter - but if scaling/performance matter for your company, you don't want to head down the garden path because your developers didn't know better.
Not knowing algorithms won't exclude you from all jobs (or even many of them), but there are some jobs where it _will_ bite you. It's your choice if you want to go for those jobs. Personally, I think they are where the cool stuff is happening, but YMMV.
You are SERIOUSLY underestimating the amount of time required to learn that stuff. In essence, the full 4 years of a CS course deals with data structures, algorithm and math. Good luck finding a project where the stakeholders are willing to wait that much. Also, unless you are a very unique snowflake, you will not have the required discipline.
On the other hand, learning a new language is accomplished in a matter of days. Learning how to code well requires experience and willingness to learn from one's mistakes.
Which a candidate with a good CS background may already have.
The learning is often sufficient to serve the needs at the moment. If I have to quickly fix my juicer, I don't under go do Electrical and mechanical engineering courses for the next 4 years.
Instead what I do is, I define the problem. Search for the solutions on the internet. The solution requires me to understand some theory and some practical aspects of things with some tool usage. It is more than sufficient to that to solve the problem for the moment.
That is how most of the software is, its practically impossible to know every thing from the book. What is more important today is given the body of knowledge can a person study and solve the problems. A person can be productive and deliver the goods with the above approach, With a little discipline.
That's how most knowledge based work happens in the 21st century.
I also see a lot of people around me trading stocks, although they understand virtually nothing about economics in detail. For the most the part they can make 10-15% profit on their investment by just using some basic analytical skills.
This is the problem with kids these days.
We can argue as much as we can about generational differences. These days you can do a lot of things without knowing much about it before hand. That's the kind of advantage internet offers you these days.
If a person is unable to leverage this to his advantage, I feel sorry for him. And I see no reason why others shouldn't do this just because he can't.
After he left I went back to learn math for interest and got really into it. I now realise that literally six months of the work he did I could do in an afternoon as I now have a deeper understanding of the mathematics behind it than he did. I'm not smarter, far from it, just have more tools to call on. And this was a guy that taught the algorithms course at a good university.
We are all capable of learning almost anything, but a lack of knowledge about the subject matter constrains your solution search space to a large degree. I believe strongly that fluency in algorithms is a minimal prerequistite to be a decent developer. It's like learning calculus without knowing trig, you can do it, but you'll be reinventing (poorly) a tonne of work that came before and you'll be slower and less accurate. It's not like it's rocket science either, you could get a basic understanding in a concentrated day of work so there's no reason not to.
In computer science, there is the notion of the NP-complete problem, for which there is no known efficient solution. But if a solution is found, it can be verified very quickly. I think the analogy holds here.
Math is unreasonably effective. Just like knowledge of basic algorithmic analysis. I don't think that should be controversial.
How do you know whether or not this is true? Until you know it, how do you go about estimating how long it will take to you to learn it? How do you even assess when you've learned "enough" algorithmic complexity for the task at hand? Can you give any reasons someone looking to hire you should believe that you can learn the ins and outs of algorithmic complexity with "very little friction"?
Do you time your app at various loads (including well beyond expectations), graph the performance and look for non-linear increases?
It was condescending to my eyes, nothing more nothing less.
If you're a visual thinker, the "shape" of an algorithm or data structure can be very helpful as well. Imagine it geometrically and think about how, say, the height of a tree compares to the length of a line with the same number of elements.
Of course, practice also helps. I'm lucky enough to get plenty of practice in school, but I think doing various condensed but nontrivial problems (think programming contests/project Euler) is probably both more fun and more practical for somebody out of school.
Ultimately, knowing running time of algorithms and behavior of data structures isn't really what's important; rather, it is just a "symptom" (in a good way) of having a solid grasp of what's going on. Just memorizing the times with flashcards is basically faking it--it might not be completely useless, but you'd be better off actually understanding everything.
I used to not have any idea about this sort of thing. My code worked fine, and I had no problems--I also never thought "hmm, I could have made this more efficient if only I knew about tree maps!". However, I now realize that the reason I never saw this was because I didn't know enough--I didn't even know enough to know I had a problem!
In short: you should learn how the algorithms and data structures work, not just for running times or interview questions, but to make you a better programmer. It definitely won't make you worse!
[1]: http://www.cs.berkeley.edu/~vazirani/algorithms.html
It's fairly in-depth but narrative in style and readable; I rather like it. One particularly nice touch is that it goes over the practical applications of the various algorithms at a high level, giving you a good idea of where they are used and why.
If you do not do much math and do not remember Linear Algebra/Discrete Mathematics, it might be best to skip the first couple of chapters and look at graphs first instead. That said, the first two chapters cover some math which is probably good to know.
The book is primarily about algorithms. It touches on data structures where needed to implement or describe an algorithm, but not much more besides (at least in the parts I've gotten through so far). I have not read any good data structures book, but have found Wikipedia to be a very good resource. I suggest avoiding overly language-specific books on the matter--I think that Java books in particular are insidious, but I am little biased in that regard.
The best approach would probably be to read through a section about some algorithm, look at what sorts of problems it can solve and then write a simple program to solve those problems. For example, when reading about path-finding algorithms, you could write a simple navigation program. I find this helps keep the material interesting and also aids retention.
Additionally, I have heard good things about Introduction to Algorithms[2] (another creative name)--it was suggested as a reference for the course, although I did not get it (Wikipedia is good enough for me).
[2]: http://en.wikipedia.org/wiki/Introduction_to_Algorithms
Recently I sat down and thought about where I want to be in 5-10 years. I don't want to be writing django apps in 10 years, I don't want to write software that sort of works some of the time, and i don't want to be a replaceable commodity programmer working on outsourced software that the real programmers didn't feel like working on, so they send it to India, or Eastern Europe(which is where I’m from). Sure, I can make a comfortable living that way, but what I want to be in 10 years is a competent expert.
I want to work in diverse fields, with people much smarter than me, and the little knowledge and experience I can gain in my career I want to pass down to younger programmers. I want to wake up in the morning and be proud that I've build things that actually matter, and not just the latest social networking pop-culture crap that many of us are dealing with now. In short, i want to e a hacker!
To do this, I decided to dedicate myself to actually learn the hard stuff that most people shy away from, just because they can get by with only some python/ruby/php and jquery knowledge. Math, CS(algorithms, data structures, languages, compilers, architectures, networks, operating systems), science, philosophy, history, art, etc. All hard stuff that I'll never need to know in order to build a web store site for a small business that barely gets the web, get paid, and go wash the car on the weekend. Even if i can never learn all of it, even a fraction is better that writing the same simple web apps for 10 years.
I'm only a little farther along in my journey than you; at 26, I finally feel confident in my abilities, but am still humbled by how much I don't know. Last month I spent hours poring over Linux network programming resources so I could implement a performant, scalable, thread-safe game server [1]. After weeks, I finally got it working--replete with tests, sane coding practices and other Good Things--and it felt so good.
Like you said: "All hard stuff that I'll never need to know in order to build a web store site..." I didn't need to reinvent the wheel--there are tons of pre-existing solutions and frameworks out there that I could pick up and use to hit the ground running. But, like most people on this site, you and I were bit by the same bug: the desire to understand how and why it works.
For me, the hard part isn't dedication to learning or writing dime-a-dozen web apps to pay the bills. The hard part is finding the right balance. I think that's probably something I'll keep learning more about until I finally kick the bucket.
If I can presumptuously offer advice, from barely a half-decade down the line: Don't give up, and learn to see the intimidation for what it is: thrill! Do as the sagacious Derek Sivers commands: whatever scares you or excites you, go do it [2]. If you come upon something that seems insurmountably complex; it could be anything: compilers, emulators, algorithms, low-level network programming... do it. You don't have to learn it in a day, a month, or even a decade, but never fool yourself into believing that it's too hard. It isn't. Take breaks to keep yourself sharp, but never give up.
[1] - http://stackoverflow.com/questions/6849239/how-should-i-arch...
The day you see such a guy, you suddenly get a feeling about the what the hell are you doing being average among the crowd of algorithm writers, while you could actually be a leader earning great money and with a big designation.
As we age we carry on a lot of financial responsibilities and money will play a huge role in the choices you make. You may give a great interview and go on to work with the brightest engineers at google and get lost in the brilliant crowd. At that time when you start reviewing your choices, you will get a feeling that you could have been unmatchable only if you had chosen a more easier career path.
In short,
There is no point being an average guy among a crowd of brilliant people.
My point was that there is no benefit in being the average among the best. But you can do wonders by being the best among the averages.
Of course you can disagree with this. But more often, all you will need is certain guiding principles in life 'which you need to learn from smart people' after that you will have to the grind work individually on your own. The sooner you learn those principles the better. There is never going to be a situation where you will be carbon copying from those smart people all over the time.
The other sort of learning, is incremental learning which happens all time, regardless of where or what work you do. Regarding specific life changing learnings, there are only going to very few of those in your whole life.
Back on topic: it's actually pretty easy to intuitively estimate the asymptotic time performance of most data structures if you sit down with a good algorithms book for a while and read through until you understand it. If you don't find everything simple the first time, go back to the beginning a few days later and read it again. This will give you big-O-estimation skills for things that aren't mentioned in the book, plus thorough understanding of the things that are mentioned.
I prefer Robert Sedgewick's Algorithms books, because the pictures are amazingly useful and abundant, but there are other good options. After a while it just starts to make sense.
Which is to say, I think you're on the right track if you don't just want to follow the popular trends, but want a chance to do something new in a way that no one has even considered yet. Which certainly sounds a lot more fun, if nothing else.
I tend to think of programming tasks being split into two major categories: applications programming and systems programming.
My definition of these terms: applications programming is writing software to be used by a normal person. Systems programming is writing software to be used by another programmer. (These definitions may be a little different from how these terms are commonly used.)
From your self description, you seem to land pretty squarely on the application programming side of that divide. For most application programming tasks, getting good performance consists mostly of selecting libraries, databases, web servers, languages, etc. with the performance characteristics your application requires, and building your application on top of them.
The system programmer is the one writing those libraries, etc. and so those performance requirements fall squarely on them.
So I would say that as long as you stick to applications programming, algorithmic ignorance probably isn't a major problem. But a company like Palantir needs systems programmers (per my definition above, even if the "clients" are just other developers within the company) which is why they need to ask algorithms questions in their interviews.
It helped a lot with basis for algorithms (terminology so you can understand what you are reading), but it didn't really teach me all of the data-structures and algorithms that I know. (There are really too many to cover everything properly/thoroughly in the extent of a course or two, even at graduate level). Also, I would have been sunk if I hadn't known a lot of it before applying to the program.
So I learned a lot of it through my own natural curiosity.
Everything concrete that I learned about data structures and algorithms started by reading Wikipedia. The CS articles are fairly accurate (it is hard to gain anything by spreading misinformation in them) and there are often times links at the bottom to the actual papers and code describing and implementing them. Start with the overview article and then read the paper. Look up any terms you don't know. Try implementing it in a language you like.
You can also Learn about data-structures in languages that you like (looks like ruby/python for you; you are in luck... those are both open source). Figure out how they are implemented, and performance characteristics. Go ahead and download the source tree and read the code.
Implement naive versions of various datastructures/algorithms yourself. See if you can play with them and improve them for various tasks. (Can I make this hash table use less memory? Give it a faster hash function? Make it a game).
I think flash cards would be a bad move, because then it starts to feel like a chore. Programming and reading and learning shouldn't be taken to like chores, they should be enjoyable and rewarding.
Tinkering with the source code for $language is also a great idea! That meshes with my empirical experience that the best way to learn is to "play". These days, it's rare for me to write code that isn't related to some specific personal project or business goal; maybe bringing back a bit of the "play" aspect is one of the keys to improving fluency.
You really start learning when you read the references, and have 5 or 6 browser windows open with web searches to things that either interested you and weren't referenced, or to terms that you didn't understand.
>That meshes with my empirical experience that the best way to learn is to "play".
It has actually been shown in educational studies that this is one of the best ways to learn; so social science seems to match up with your experience as well.
Later on I found some Stanford lectures, particularly Programming Abstractions by Julie Zelenski (around lecture 14). After watching that lecture I was able to classify my linked list sorting attempt as a selection sort. I was pretty excited that I wrote a selection sort without even knowing what kind of sorting I was doing. I have yet to use my newly acquired knowledge at work but I'm now confident I can spot certain sorting algorithms and I'm much more aware of when to use each.
If anyone is aware of any other resources like books, online tutorials or videos I would love to hear about them!
I think for interviewers, this approach to quizzing on algorithms and data structures is probably just a well-known practice and probably lacks correlation with the work of a specific job role most of the time.
If you aspire to work somewhere that has a demand for deeper algorithmic work, you do need to understand algorithms and data structures. I think this is probably a smaller number of potential jobs than many of us on HN would like to admit - there is simply a large number of mundane IT/dev jobs where the naive imperative solution will be just fine.
I would skip flash cards, but try to find small projects at work that require algorithmic and data structure thinking. Then you get some applied experience that will "tell a good story" at an interview plus build your analysis skills.
I think for a lot of jobs, even being able to talk about an algorithm and data structure design that you personally did will put you way out in front of a number of candidates.
Algorithmic complexity isn't about performance, it's about scalability. A hand-written implementation in assembly that's O(N^2) will be slower than an implementation in Basic that's O(N) (or even O(N log N)) for a sufficiently large N.
I suggest picking up Programming Pearls, they had an example of a BASIC program on C64 vs. a Fortran program on a mainframe (the book is from the 80s) demonstrating this.
That said, if building basics web apps is all you want to do (e.g., internal enterprise applications) then you don't need this knowledge. However, the harder stuff (whether algorithmic, systems, etc...) like (but not limited to) what Palantir works is what I find more interesting.
Whenver you do start to approach values of N for which you need to fine tune, you're going to be researching and profiling and optimising the hot code anyway.
I'm not saying you don't need to know algorithms, but you don't need to know the big O for every sorting algorithm / insertion cost to each type of tree off the top of your head. A rough idea of whats terribly inefficent is fine for most tasks.
Watch it before deploying those big joins that worked so nicely on your development data set, then.
- Operations that take the same amount of time regardless of the input are O(1). ie: 1+1 takes just as long as 10000+10000 (okay, not really, but it's a reasonable assumption.)
- Doing a small sequence of operations runs in O(maximum of all operations). Doing 5 adds (which are O(1)) runs in O(1). Doing an O(n) operation followed by an O(k) (where k > n) runs in O(k) time.
- Looping n times over O(k) operations runs in O(n*k) time. (Assume n is fairly big.)
- Due to the structure of a tree, accessing a node is generally O(depth of the node). Max depth = log_m(number of nodes) for a full tree. (Where m is the number of children each node has. For a binary tree, m=2)
- From there, you can pretty much combine these rules to analyze many algorithms. These aren't by any means all of the rules, but they are some of the most useful in my experience.
I'm not sure if I'm still misunderstanding you, but here's an example of what I meant.
Say, for whatever reason, you want to populate a binary tree with k items of random data:
for(int i = 0; i < k; ++i) {
int data = rand(); // Let's assume this is O(1)
tree.insert(data); // O(log(n))
}
The inside of the loop runs in O(log(n)) time because O(log(n)) > O(1). We're doing it k times, so the total time is O(klog(n))Now, if you wanted to do this for m trees:
for(int j = 0; j < m; ++j) {
for(int i = 0; i < k; ++i) {
int data = rand();
tree[j].insert(data);
}
}
We already know that the inner loop runs in O(klog(n)). Since we've just added a loop around that, it's easy to see that the whole thing runs in O(mklog(n)) time.This is not necessarily true for all cases. (It is for yours.) It's possible for interaction to exist between a loop and its contents, such that the total time is not m times the running time of the interior of the loop.
for (int i = 0; i < data.length(); i++)
bubble_sort(data);
That's a trivial case but sufficient to prove the point. Bubble sort runs in O(n^2), and it looks like we're doing that n times, so the whole thing runs in O(n^3). But that's not true, since bubble sort runs in O(n) when the array is already sorted, so the whole thing is still O(n^2). In other words, the first iteration of the loop induces a side effect that affects all later iterations.(Also, if data is a linked-list, length() could be an O(n) operation. That would make this O(n^3) or O(n^4) ;))
That's probably the case, and there's no shame in that. The companies who ask these questions do so because their engineers deal with these kinds of scaling challenges every day. They can't afford to have people casually slip in an O(n^2) algorithm when an O(n lg n) or O(n) algorithm would do. If you don't have the experience of working in this kind of environment it's not a dealbreaker, you just need to show an awareness of the big-O implications of your algorithms, which will most likely come from some combination of study and practice.
> Is my lack of fluency preventing me from understanding just how important it is
Probably not -- if you're working at a small scale, then big-O probably truly is one of your lesser concerns (unless you write an O(2^n) algorithm, which is less common to happen accidentally).
I'm skeptical of that statement. Some of the engineers at, say, Google, deal with code complexity and scaling every day. Most probably don't. Certainly, most at the non-Googlish companies hardly ever deal with this. Yet the majority of interviews I've gone to over 12+ years have involved significant questioning about algorithmic complexity.
I agree with your statement about awareness of Big-O, but often companies seem to be looking for over-stressed obsession, even for jobs which don't utilize it.
I am an engineer at Google, and basically all of the engineers I work with have to scale their software in least one dimension such that big-O complexity is a significant (and daily) concern. What I mean by "daily concern" is that the check-ins are happening on a daily basis would be noticeably inefficient if they used an O(n^2) algorithm instead of an O(n) algorithm, for example.
> Certainly, most at the non-Googlish companies hardly ever deal with this.
My main experience is Google and Amazon, so I couldn't say. I was meaning to talk mainly about Google/Amazon/Facebook/Twitter-like companies. I'm betting Palantir is also one such place.
We have a data base that gathers about a 5GB of market data a day and we have to run algorithms to analyse the data and analyse the behaviour of our system. Efficient algorithms become very important.
Maybe I'm unusually hardcore? I'm definitely not all about the algorithms, but I work on a lot of systems programming.
The other thing is that often you don't realize that what you're doing requires thinking of this until somebody else has to go fix what you wrote. The fix will even look very simple. The insight going into the fix isn't as simple, though.
And I've worked at a long series of companies that don't. That's the thing: different strokes for different folks, as it were.
Maybe I'm unusually hardcore?
I think it's less about degree-of-core-ness and more about platform and domain knowledge. Personally, if I were hiring for what I consider to be a fairly typical company, I would be looking mostly for ability to consistently get functional, bug-free code running. I would likely seek stronger algorithmic knowledge in some small ratio of employees.
I guess I feel strongly about this because I think it's fundamentally disrespectful to all coders, and ignores the tremendous variety of tasks and skills out there. A self-taught hacker who can get a great product going in a short time may be just as important and valuable to a company as the algorithm-strong coder who catches scaling problems before they come up. When it comes down to it, the goal is to create product and value, and that happens in many, many different ways.
The fix will even look very simple. The insight going into the fix isn't as simple, though.
That's true of the majority of bugs I've written or come across, whether its related to performance, crashing, or unpredictable behavior. In fact, looking at fixes that coworkers make to your own code can be a tremendously enlightening (and humbling) experience.
Then I would hope they have a good sense of usability, if they are writing user facing code. And I would hope they have a good sense of algorithms and other aspects of scalability, if they are writing server side or systems code.
Not at all. It means that humans are complex and ranking them is extremely difficult.
My issue is with the fact that I've met too many very smart people who can prattle on about Big-O and optimal architectures for hours, but when it comes time to get dirty and finish a job, they lose interest, produce unmaintainable, over-engineered nightmares, and/or turn out not to actually understand the platform well enough to execute a clean solution.
if you don't know the time it really should take, then you just don't know what you have a performance problem. Dunning-Kruger in application to software engineering. Too typical a situation in the industry.
Coding is an engineering discipline: it's all about tradeoffs. Bugs and reliability. Performance. I know to focus on what is important to get a working product.
the Dunning-Kruger is exactly about ability to notice
>If everything I write runs in a fraction of a second,
where are different fractions of a second out there. Some are slow, some aren't. One either knows which are which or he doesn't.
>why would I waste my brain optimizing it to make it faster, when all I'd achieve is introduce tricky bugs.
that is one of the main points where effective implementation knowledge [incl. algorithms] comes to play. Typical "blackmail" in the industry - if performance then bugs.
>Coding is an engineering discipline: it's all about tradeoffs. Bugs and reliability. Performance. I know to focus on what is important to get a working product.
man, you sound like a typical PM when schedule is pressing and the things are started to be pushed out of release, and a pile of slow sh!t is released as result.
the Dunning-Kruger is exactly about ability to notice
It seems like you are saying that every programmer ought to go out of his way to become fluent in algorithms, because without fluency he or she will never notice when their code is running slowly.
If so, I disagree. It requires no skill to notice whether code is running slowly--you needn't look further than my techno-skeptical dad muttering, "Jeez, this thing takes forever to boot up" as he regards his desktop with disappointment. I think this is what the grandparent commenter was talking about: if I'm not fluent in algorithms, but my dad doesn't think it's slow, then where's the problem?
"Premature optimization is the root of all evil."
this "forever" consists of myriad of "a fraction of a second"-s, with each fraction individually not being "notieably slow" and thus not "prematurely optimized".
And if not optimized "prematurely" (ie. written efficiently from the start), then after-the-fact optimization, if happens at all, would shave only a fraction out of the "forever" - thus it frequently doesn't happen at all because of such low projected ROI.
My personal experience completely contradicts what you're saying.
Despite the cushy comforts of server-side scripting languages, I have experienced the occasional performance or scalability problem, and in every single case, I wrote inefficient code on the first pass, discovered unacceptable slowness at a later date, then found the bottleneck and optimized it.
Perhaps I am a brilliant super-coder (unlikely), but I have never ignored a performance problem because I didn't think I could improve it enough to be worth the effort.
One of his points - with which he uses an id game as an example - is that sometimes the naive implementation is the best implementation. His example has to do with loading levels at startup. The written code was, from an algorithmic perspective, inefficient. It was written in such a way to optimize for developer time. His point was that in this circumstance, that was the correct thing to do because this was not a performance critical part of the code, and naive implementations are easier to maintain.
2011 Programmer Cost/Benefit reality:
1) The chance my app will be so heavily used that it requires deep knowledge of many algorithms is pretty low.
2) The chance my app has serious marketing or business model problems is pretty high.
3) The extra cost of using a scalable platform (PaaS) like Appengine, Heroku or plain EC2 is less than both the cost of my time to learn or relearn all of those algorithms and the cost of setting up my own scalable platform.
I see far more business model/marketing problems than scalability/performance ones.
However, once the number of things you're dealing with gets up to, say, the millions, algorithmic complexity can really bite you in the ass and no matter how much hardware you throw at it (rented or otherwise), if the work that a single node needs to do is unreasonably complex, your whole app will be slow for every user, even if you have enough capacity to handle many simultaneous users.
In the mobile space, you can think of algorithmic complexity being a proxy for battery life - if you can make it cheaper to compute, you do less overall work, and the battery lasts longer.
I'm just saying most paid programmers are not dealing with the problem of how to handle processes that involve millions of users, but they do have problems with marketing their app or monetising it. Therefore spending their weekend learning something like Dijkstra's Algorithm may not be the best use of their time, but finding ways to better understand the needs of their paying users probably would be time well spent.
Are you sure about that? Have you never tried to do something, found it was taking forever, and gave up? Maybe you concluded it was impossible, or you found some way to approximate what you needed.
I am another self-taught programmer, and believe me you are going to be kicking yourself once you do learn a few good algorithms and data structures. Your favorite accomplishments -- intricate beasts that you felt you had tamed with much sweat and effort -- are going to turn into five or six lines. Or maybe two or three small, easy to understand programs. Impossibly large amounts of data are going to look easily tameable.
> How does one achieve this?
Not so hard - read a good book. There are lots.
I'm specifically interested in books/other resources that lend themselves to self-study. It's easy enough to look up what MIT is using for their Intro to Algorithms course, but it's harder to gauge if a book or other resource is suitable for usage outside of a classroom setting. Bonus points if it has a practical focus so that I can quickly add the gleaned knowledge to my real-world toolkit.
As for "outside of a classroom setting", the best book I can recommend is "The Algorithm Design Manual" [2]. It is worth its weight in gold. Very user friendly, as I never though an algorithms book could be. It contains dense material, but at the same time reading it feels like reading a good fiction book. I first heard of it while reading Steve Yegge's post "get that job at google"[3], bought a copy and, wow, what an amazing book.
[1] http://mitpress.mit.edu/algorithms/ [2] http://www.algorist.com/ [3] http://steve-yegge.blogspot.com/2008/03/get-that-job-at-goog...
http://www.amazon.com/Algorithm-Design-Manual-Steven-Skiena/...
I was a bit flummoxed at first because algorist.com doesn't tell you how to buy the thing, and the Kindle edition appears to be out of date (based on the first edition, obsoleted by the second edition from 2010).
I should have linked to the Amazon page in the first place (who am I kidding?). You linked to the correct version.
I find this book readable and interesting; it does tie the algorithms to practical applications at a high level. It is language-agnostic, so it should be a good fit for almost anybody.
The book was written as a companion to Introduction to Algorithms by CLRS and is comparatively lighter on theory, but still a handy desk reference.
disclaimer: it was written by my undergraduate advisors
Then I think it will stick.
If you really don't need this info, then don't waste your time. To work at a place like Palantir, you do need this info.
What a waste!
And what is wrong with one sub-thread dipping into an utterly related topic? Are you suggesting that no discussion should ever shift from one aspect of a topic to another? Or are you suggesting that every programmer, anywhere, ever, should obviously learn algorithms until they are completely fluent? Both of those are baffling to me, as the former would be a completely unstated expectation in the entirety of internet discussion forums, and the latter is what we are discussing in this sub-thread!
This is one of the most interesting threads I have ever read on Hacker News. It contains a fantastic breadth of perspectives and has remained admirably civil and candid. I've had 2 people e-mail me just based on this thread, and I've purchased two books just based on this thread. I take umbrage that you would call it a waste.
I'm self-taught and I've read and learned about computational complexity several times from various CS books and later Internet since I was maybe fifteen years old. I know how O(1), O(lg n), O(n lg n), O(n), O(n^x), and O(x^n) scale and which kind of algorithms roughly belong to which order of complexity.
However, keyword being several times.
I so rarely bump into these that I don't actively remember if heapsort is lg n or n lg n, or how the best-case, average-case, and worst-case complexities differ exactly between heapsort, quicksort, and mergesort. (I do remember that mergesort had a good worst-case behaviour in comparison to the others, at least quicksort, but I'd really have to check the bounds separately.) To mitigate this, I've guiltily re-learned them several times--I like reading Knuth or other CS books per se, just for fun--but like anything you don't need you do have a hard time remembering.
However, I do recognize them all being lg-something and looking up the various bounds is just a Google search away. Further, I do recognize the complexity orders in the sense that I might prototype something and initially stash items into a linked list but make a mental note that accessing the list can potentially become a bottleneck because it's O(n) so I shall reserve some mind power to change it into some O(lg) tree or ordered array at some point.
But at the other end the truth is that you just have to have some idea about complexity. You generally don't need more than that, and when you do you can just re-study that portion of the subject in detail from a huge number of web pages.
For example, it's useful to recognize the obvious bottlenecks of O(n^x) and O(x^n) but if you do, you don't bump into them anymore. You might bump into O(n) bottlenecks because you left them there yourself, probably on purpose, but since you recognize what linear complexity can do you will generally just change the relevant data structures into O(lg something) and be done with it. And if O(lg something) code becomes a bottleneck, you usually have stupid access patterns elsewhere in the code; I don't remember ever seeing a binary tree alone having become the real bottleneck in any program with the rest of the code being optimal.
What's interesting is that I more often bump into problems with the physical representation of the data structure than the computational complexity. A big naive hash table can cause lots of cache misses unless you deliberately work to align your items withing as few cachelines as possible. The difference between accessing five cachelines rather than five hundred cachelines can be blasting. I know this kind of optimization wouldn't scale towards n⇒∞ generally but it can have a big effect on real-world programs.
I didn't have a traditional CS education in college. Maybe there's some kind of magic that happens in Algorithms [1-3]01 that permanently etches these characteristics into your brain. But whatever it is, I missed out.
My main problem is that I don't seem to need this information to do what I do. I work predominantly with server-side, interpreted languages, and I just don't run into the bottlenecks and performance problems that Big O-knowledge seems to mitigate. Maybe I've been lucky. Maybe it's because none of my personal projects have gotten popular enough to be subjected to the kind of load that reveals such problems. Maybe it's because I haven't worked on the kind of project that needs this sort of attention. Whatever the reason, I simply have never hit a point in my work (which I assure you has been non-trivial at times) when I sat back and said to myself, "Gosh, if only I were more familiar with the complexity breakdown of the classic data structures, I would be able to solve this problem much more effectively or efficiently."
The thing is, I know that I'm perfectly capable of nurturing greater fluency in algorithms, so it seems like a waste to inevitably flub the more demanding portions of algorithm-based interviews. So what should I do? Is the answer as simple as biting the bullet and using flash cards until I know it all by rote (which feels like cheating), or am I "doing it wrong" somehow? Is my lack of fluency preventing me from understanding just how important it is (a la Dunning-Kruger)?