Want to prepare for your next interview? Go slowly to get there fast.
Dan Svorcan
Software engineer & career mentor who believes that every "no" brings us one step closer to a "yes." I help people find the job of their dreams. Want to know how? Visit careercompass.dev
Preparing for an interview is no different than learning (or re-learning) a new skill. Do want to learn how to play a guitar? Learn a new language? Figure out a new technical framework or a tool? The key is to go slow and deep.
A long time ago, I was an active bass player preparing for a concert, which included a very tricky piece of music. That piece of music was "Jaco Pastorius - Donna Lee" which is (to this day) the most difficult piece of music I ever attempted to play. Case in point: I spent 4 months practicing only a tiny section of the song.
Why on Earth did I spend about 80% of my time working on just 3% of that song? Because it was the most difficult part of the entire concert! I knew if I master that part, the rest of the concert will be easy.
Years later, the same approach helped me land jobs at LinkedIn and Microsoft: I focused on the most difficult parts of interviews and practiced those extensively!
There is no such thing as a shortcut
The strategies I am about to recommend focus on technical interviews for software engineers, but the principles are universally applicable for any role, and any skill. If I could teach you one thing - it would be to go slowly to get there fast.
There is no such thing as a shortcut. I know because I spent years trying to find shortcuts and faster ways to learn. If I spent that time actually studying, I would've saved more than just time. I could've avoided the frustration and anxiety that comes with looking for shortcuts only to find dead ends.
Scott Devine sums it up the best:
"If I could give my younger self a bit of advice, it would be: stop looking for shortcuts and just do the work. It's so easy to spend just as much time looking for shortcuts as it is just to do the work. So just do the work"
Job interviews
Interviewing is a separate skill from our day-to-day jobs. That means we need to learn or re-learn how to interview each time we embark on a new job hunt.
If you're a software engineer, you probably know (and dread) the technical interviews because of the data structures & algorithms. If you're not a software engineer, then all you need to know is that technical interviews are like exams in college. Your interviewer gives you a problem and watches intently as you try to solve it in front of them - either on a whiteboard, or on your computer.
There are 2 things that make technical interviews particularly difficult:
The best way to overcome problem No. 1 is to simply interview (perform) as much as possible. That's why my job hunting mantra is "Nothing prepares you for an interview like another interview".
The best way to overcome problem No. 2 is to stop looking for a shortcut, and go slow and deep, which what the rest of this article will focus on.
Slow and deep (80/20, 80/10, or even 80/3)
You probably heard of the Pareto principle which states that for many outcomes, roughly 80% of consequences come from 20% of causes.
That means we should spend most of our energy solving the most impactful problems. In my example above, I spent 80% of my practice time learning just 3% of Dona Lee. If you are preparing for a technical interview, Pareto principle is your best friend.
A common strategy amongst software developers is to use Leetcode and just solve as many problems as possible. Leetcode is a great resource, but randomly solving hundreds of problems is an awful strategy that just leads to stress and frustration because you never know if you're going in the right direction.
The biggest problem with this approach is that you always feel the pressure to solve a problem and move on to the next one. You never have the time to slow down and spend 3 days (or even a week) on a single problem in order to deeply understand it. It sounds counterintuitive, but deeply understanding a single problem is much better than quickly solving 10.
If you solve 10 problems quickly, they will all seem different and unique, like starting from scratch each time. However, if you spend the same amount of time solving a single problem and building a deep understanding of it - you will develop pattern recognition. You will understand the building blocks that are shared amongst all 10 problems and more. It will be slower at first, but later it'll be much faster because you will see similarities between different problems and it won't feel like "starting from scratch" each time.
So what to do instead?
Quick detour - why do we need data structures in the first place?
Let's say you're trying to find your shoes. You can walk into your room, take a look around, and quickly identify the shoes. Your computer can't do that. Instead, it relies on memory which stores information (bits) in buckets (capacitors).
In the picture above, your computer has to store information (bits) wherever there's available space, and then has to retrieve it somehow. In fact, the sole reason we're studying data structures and algorithms is because of computer memory (RAM). Just like we hold thoughts in our heads, computers hold their "thoughts" in memory - a collection of buckets where data is stored randomly, in whichever slot is available.
Data structures help us (humans) think about storing and retrieving information from computer memory quickly and efficiently. Your computer is often forced to store related bits of information in very different and distant slots in RAM, based on available space. In fact, this is similar to how cities grow and develop, and sometimes we end up with related buildings in very different parts of the city. For example, government buildings, or same-company offices scattered throughout the city. The older the city, the bigger the problem.
As the cities grow, so does the congestion, and new buildings are placed wherever there is available space. Unlike RAM which frequently updates its memory slots, we usually can't move buildings and organize them better. I say "usually" because because there are exceptions - for example Egypt is building a new capital city and one of reasons is to put government buildings closer together for increased efficiency.
Back to data structures and interviews.
Focus on one data structure at a time
Here are some of the most important data structures I would recommend you start with (in no particular order):
Study only one data structure at a time, and study it deeply. Forget about all others until you feel comfortable with the current one. This may seem slow, but each subsequent data structure will be easier to master because many concepts will carry over.?
领英推荐
Each data structure has a couple of common algorithms that go with it. For example, depth-first search (DFS) and breadth-first search (BFS) are commonly used with trees. With arrays its sorting, and with graphs its path-finding.
The best way to understand an algorithm is to understand the data structure it's used for. If you understand that trees always have a root node, then you'll understand that BFS is better when you want to find a shortest path between two nodes, and DFS when you want to traverse the entire tree with a lower memory footprint.
The problem you're trying to solve will usually have one or more suitable data-structures you could use. Once you choose a data structure, it will then dictate which algorithm(s) would work best and which tradeoffs you have to accept.
Forget the code
Most software engineers I know, myself included, are eager to jump into coding, and solve the problem by coding. Experience has taught me this is almost always the wrong approach.
Think of it this way - writing an essay is easy once you know what you want to say. Similarly, it's a lot easier to write code once you know exactly what you want the computer to do.
Before jumping into code, think of your problem as a "real world problem". I believe this is the most difficult part of a technical interview because it can be quite tricky to translate the problem from computer science concepts to real world and back to code, simply because computers have to deal with obstacles we don't - see the how RAM works above, and how computers find things in RAM.
For example, I like to draw trees on a piece of paper when I'm dealing with a tree-type problem. On each branch of my tree there is a small hanging box with an item inside. Boxes contain different items, for example an apple, an an orange, or a pencil, etc.
Box contents don't matter - what matters is that you're recreating the scenario your computer must deal with when finding things from RAM.
Take a look at a picture below. Each branch has a box with a hidden item, so how would you find a box with a pencil if you ever found such a tree? You would probably do it just like your computer - you would visit one branch at a time, and open the boxes one by one until you find what you need.
Play around with it
Explore different ways you can find the desired item on your tree. Draw a tree of a different shape and see if DFS or BFS algorithm would be faster or easier. Turn it into a game until you instinctively understand your tree and different ways to find things on it.
Maybe the tree example doesn't quite work for you. If that's the case, then change it into something else! Maybe try thinking about scattered shoeboxes, and finding an object of interest inside of them. Or perhaps you enjoy playing with marbles, so now you have to sort them by color, or size.
It doesn't really matter what example you use, the important thing to remember is that all "computer problems" are actually real-world problems, just abstracted differently.
Before there were personal computers there were digital calculators, and before that there were electro-mechanical calculators. Going further back in history, there was abacus, and tally marks. All of these inventions came as solutions to a real-world problem of counting things such as apples, money, and other objects of interest.
Learning data structures and algorithms is very difficult if you don't understand their nature and purpose in the first place. That's why I recommend taking your time to play with the concepts, and going back to their origin.
For example, the origins of the bubble sort algorithm could come from a fruit seller in ancient Rome who needed to sort his apples by size, and charge premium prices for his largest apples. I am totally making this up, but it helps me remember how bubble sort works - I imagine myself sorting apples by continuously swapping two apples until all of them are sorted by size.
Finally, translate to code
Now that you understand the concept deeply - it's time to translate it to code. This should actually be the easiest step of the process because at this point you have a clear plan of what's needs to be done.
Create all of the data structures I mentioned above in your programming language of choice, then use the algorithms associated with those data structures and play some more!
Here's an example of a tree I built in JavaScript so I can play around with it:
// javascript example of a tree
const Tree = function (value) {
this.value = value;
this.children = [];
};
Tree.prototype.addChild = function (value) {
const child = new Tree(value);
this.children.push(child);
};
Tree.prototype.DFS = function (targetValue) {
console.log(this.value);
if (this.value === targetValue) {
return targetValue;
}
for (let i = 0; i < this.children.length; i++) {
this.children[i].DFS(targetValue);
}
return -1;
};
Tree.prototype.BFS = function (targetValue) {
const queue = [this];
while (queue.length > 0) {
const currentNode = queue.shift();
console.log(currentNode.value);
if (currentNode.value === targetValue) {
return targetValue;
}
for (let i = 0; i < currentNode.children.length; i++) {
queue.push(currentNode.children[i]);
}
}
return -1;
};
console.log("Tree");
const myTree = new Tree(1);
myTree.addChild(7);
myTree.addChild(32);
myTree.children[0].addChild(8);
myTree.children[0].addChild(101);
myTree.children[1].addChild(78);
myTree.children[1].addChild(14);
console.log(JSON.stringify(myTree, null, 2));
/* console output:
{
value: 1,
children: [
{
value: 7,
children: [
{
value: 8,
children: [],
},
{
value: 101,
children: [],
},
],
},
{
value: 32,
children: [
{
value: 78,
children: [],
},
{
value: 14,
children: [],
},
],
},
],
};
*/
// console output: 1, 7, 8, 101, 32
myTree.DFS(32);
// console output: 1, 7, 32
myTree.BFS(32);
And here's a picture representing the same tree in two different ways:
Another great tool I use to study data structures and algorithms is https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
Here's an example of a Binary Search Tree. I first built it with the visualization app, then I implemented the tree in JavaScript, and then I compared my output with the visualization app to make sure they're identical.
// JS example of a Binary Search Tree
const BinarySearchTree = function (value) {
this.value = value;
this.left = null;
this.right = null;
};
BinarySearchTree.prototype.add = function (value) {
const nodeToAdd = new BinarySearchTree(value);
let node = this; //starting at the root;
while (node) {
if (value < node.value) {
if (!node.left) {
node.left = nodeToAdd;
node = null;
} else {
node = node.left;
}
} else if (value > node.value) {
if (!node.right) {
node.right = nodeToAdd;
node = null;
} else {
node = node.right;
}
}
}
};
const myBinarySearchTree = new BinarySearchTree(10);
myBinarySearchTree.add(2);
myBinarySearchTree.add(21);
myBinarySearchTree.add(22);
myBinarySearchTree.add(16);
myBinarySearchTree.add(7);
console.log(JSON.stringify(myBinarySearchTree, null, 2));
/* console output:
{
value: 10,
left: {
value: 2,
left: null,
right: {
value: 7,
left: null,
right: null,
},
},
right: {
value: 21,
left: {
value: 16,
left: null,
right: null,
},
right: {
value: 22,
left: null,
right: null,
},
},
};
*/
Take detailed notes and learn from them
Nothing can prepare you for an interview like another interview. You can be a master of data structures and still fail an interview. Similarly, you can be an amazing interviewer but fail because your technical knowledge is not quite there yet.
The most time-efficient way to prepare both technical and interviewing (communication, live performance under pressure, etc.) skills is to interview as much as possible, take detailed notes, and then improve based on your notes. Do you struggle with path-finding algorithms? Focus on those. How's your knowledge of system design? Watch a course on that. How about behavioral questions? Maybe practice with a friend.
The key is to systematically discover your own weaknesses and turn them into strengths one by one, and you'll land that job offer sooner than you expect!
What do you think? What's your experience with technical interviews and preparation for them?
? ?????? ???????????????????? | ? Content Marketing | 2x Boost Revenue ?????| 3+ years of experience Successfully managed over flexibility
7 个月Great