Data Structures for Technical Coding Interviews[Complete Guide]
Data structures are super important to know for technical coding interviews and computer science in general. And so in this article, I’m going to be breaking down some of the most popular data structures out there: what they look like and how they operate, real-world examples so you can actually picture what I’m talking about, plus their time complexities, but more on that later.
And if you’re new here, hi, my name is Zad. I have a bachelor’s and master’s in computer science from Georgia Tech. I have software engineering experience working at top tech companies like Amazon, and every single day I help hundreds of thousands of people break into tech.
Understanding Big O Notation
Before we get into any particular data structure, we do need to understand one big concept called Big O. This is our way of measuring speed and efficiency, how well data structures are actually operating in different scenarios.
For example, if I’m in New York and I want to go to California, I could walk there, it might take me a month. I could bike there in a couple weeks. I could drive there in a few days, or I could fly there in just a few hours. Different vehicles are optimized for different scenarios, just like different data structures are also optimized for different scenarios. But for vehicles, we measured the by miles per hour, but for the speed of data structures and how they operate, we use time complexity or Big O notation.
The Four Types of Big O Notation
If you’re not understanding this, let me break down four different types of Big O notation.
O(1) – Constant Time
First one we got, O of one, constant time. This is the fastest an algorithm can operate, think like rocket ship speed of light. O of one means the operation takes the same amount of time no matter how much data there is.
Imagine you have a grocery list and you want to grab just the first item on the list. Whether that list is five items, 500 items, 5,000 items, the operation is the same exact thing. You just need to take the first one instantly. There’s no extra effort despite how long the list is, so it’s super fast and super efficient.
O(N) – Linear Time
A level above that, we have O of N, linear time, where N in this case represents the amount of data that we have. This is still a pretty fast operation, so you can imagine not speed of light, but like supercar. And specifically, O of N, this is when the amount of data increases, the time it takes grows at that same rate.
For example, if you have a list of names and you need to find a specific name, the worst case is you have to check every single name until you find that name. If you have a list of 10 names, you might have to do 10 checks. If there are 1,000 names, you might have to do 1,000 checks. We don’t know the position in the list like we did for the O of one scenario. And so as the data increases in size, it takes longer because there’s just a longer operation, just more to deal with, but it’s a very predictable increase.
O(N²) – Quadratic Time
A level above that, we have quadratic time, O of N squared. Think of biking from New York to California. I mean, like, very, very slow. And this happens when every single item in a data set needs to interact with every other item.
Imagine you have a classroom full of students and each student has to shake hands with every other student. If there are 10 students, that means 10 * 10, 100 handshakes. If there are 100 students, that is 100 * 100, 10,000 handshakes. The amount of work this operation has to go through grows way too fast the more students that are added into the mix. And if you have an algorithm that takes O of N squared time complexity, just know that’s a really slow, really bad algorithm and chances are there’s a better scenario.
O(log N) – Logarithmic Time
Now the fourth scenario I want to talk about is a slight curveball and that is O of log N, logarithmic time. And this one is faster than O of N, but slower than O of one, so it’s not the speed of light, it’s like the speed of sound. It’s still really fast.
An example for you to understand this is imagine trying to look up a word in the dictionary. Typically, if you have like a random word, what people generally do is they open up the dictionary to the middle, somewhere in the middle. And from there, you decide, does the word I’m looking for come before or after the current page I’m on? And so depending on that, you’ll jump forward or backward and you’ll repeat that process until you find your desired word.
Each time we’re jumping pages, we’re cutting the amount of time that we’re looking in our search by a half. We’re not going through every single page in a dictionary, that would be O of N, but rather, we’re going half and then half of that, half of that, and the search space of the operation just gets smaller and smaller. And actually, if you look at a logarithm graph, at a certain point, as you keep increasing the input, the difference in the output is so small and so marginal. And so these are the different time complexities that different data structures can have.
Data Structure #1: Arrays
And now that we understand how things are getting measured, let’s start off with our first data structure, and we’re going to be talking about the array.
Think of an array like a row of middle school lockers. Each locker has a fixed position and you can quickly go to any one of them just by knowing its number. Arrays store data in a contiguous manner, meaning all elements are placed side by side by side in memory. Because each element has a specific index, retrieving a value is extremely fast and you can go directly to its position without like searching.
However, if the array is already full and you want to add a new element, that can be a little tricky because you can’t just squeeze another item, it’s a fixed size, just like you can’t add a new locker, you might have to break down a wall. Similarly, you need to create a new larger array and all existing elements must be copied over, and then the new element can be added. But there is a structure that’s similar to an array that handles this resizing a little bit better. If you know which one I’m talking about and why it’s better, let me know in the comments down below and I might give you a shout out in my next article.
Array Time Complexities
In terms of time complexities, accessing any element by an index is an O of one operation, so it’s super efficient. Inserting an element at a position is also O of one if you’re simply replacing an existing item, but inserting a value beyond the array’s size requires creating a whole another array, which takes O of N time because you have to copy over a whole array. Deleting an element is also O of N because once an element is removed, all subsequent elements must shift down to maintain the array’s contiguous structure, unless you’re deleting at the very end of the array, in that case it’s an O of one because you’re just removing the last element and there’s no shifting downwards.
Data Structure #2: Linked Lists
The next data structure we’re going to be talking about is the linked list.
Think of a linked list like a train where each car is connected to the next one. If you want to reach a specific car, you can’t just teleport to it, you have to start from the front and move through each car until you find the one that you need. In linked lists, each element is stored in a separate node and each node contains both a value and a pointer to the next node in the sequence. This makes linked lists more flexible than arrays since you can easily add or remove elements without worrying about shifting everything around. However, accessing specific elements is slower because you have to traverse the list from the beginning to find it.
Linked List Time Complexities
So in terms of time complexity, accessing an element by an index is an O of N operation because you actually have to go through the list, there’s no index inbuilt into the linked list. Inserting an element at a position is an O of one operation if you already have reference to the node that you’re trying to insert around, but if you actually have to search for it, once again, you’re traversing the list, so that’s going to be an O of N operation. Deleting an element, similar to inserting, is O of one if you have the right reference because all you have to do is just switch around the pointers, but if you have to search for that reference, it’s an O of N operation once again.
The nice thing is, unlike an array, deleting from a linked list doesn’t require shifting elements around, so sometimes it can be a little more efficient in this type of use case. Plus, there’s also no resizing issue because it’s just nodes and pointers, there’s no like fixed structures that you have to deal with.
Data Structure #3: Stacks
The next data structure we’re going to talk about is the stack.
This is a simple structure that follows a last-in, first-out principle, meaning the last element added is the first one to be removed. Think of a stack of chips, you have to eat the top one first before you can eat the next one. Each element in a stack is stored in an ordered manner, but unlike arrays, you can only access or modify elements from the top of the stack. This makes retrieval and insertion extremely efficient because there’s no shifting around.
Stack Time Complexities
For the Big O time complexity for a stack, there’s no accessing really at a particular index because you only take or remove from the top itself, but if you have to access or search through a stack, that would be an O of N operation because you have to go through each element one by one by one, there’s no indexing. Inserting an element, which is called pushing onto the stack, is an O of one operation because you simply add the element to the top of the stack without affecting any other structure within the stack. Deleting an element, which is called popping from the stack, once again is an O of one operation because you only have to remove from the top of the element, there’s no dealing with the other elements when you’re taking or removing from a stack, so it’s highly efficient for adding or removing. Plus, it’s very widely used in depth-first search, but more on that later.
Data Structure #4: Queues
The next data structure we’re going to talk about is the queue, and unlike a stack that was last-in, first-out, this is a first-in, first-out, which means the first element added is the first element to be removed.
Think of it when you’re standing in line at the store, the person at the front gets to the checkout first and then they get dealt with first. Any new people that want to join the line has to join in at the back and must wait their turn till they come to the front. Each element in a queue is stored in an ordered manner, but unlike an array which is also ordered, these elements can be added only in the back and removed in the front.
Queue Time Complexities
For the Big O time complexity of a queue, just like a stack, you can’t access elements by their index, but for some reason if you have to go through the whole queue to find a certain element, that would be an O of N operation to access or search if you’re not just trying to access the first element there. In terms of insertion or deletion, those are O of one operations because you add to the back, remove from the front, and it’s just continuous. Think of a stack but in slight reverse order. Plus queues are highly used in breadth-first search and Spotify music.
Data Structure #5: Heap (Priority Queue)
The next data structure we’re going to talk about is the Heap or Priority Queue.
Think of a Heap like a pyramid of stacked boxes where the smallest box is always at the very top. You don’t randomly grab a box from the middle, you always take from the top, but specifically for heaps, they actually always need a box to be at the top, like if any boxes are removed within the pyramid, they need to readjust so there’s a box still at the top so it can maintain that structure.
Also, there are two types of heaps that you need to know. First is a Min Heap where every parent is smaller than its children and the top element is the smallest, while in a Max Heap every parent is larger than its children and the top element is the largest.
Heap Time Complexities
For efficiency, accessing an element by its index is not a general operation, but if needed it would be O of one to access the top element, which we call the root, and O of N for any arbitrary elements within the Heap. Inserting an element is an O of log N procedure because first it’s added into the Heap and then because of the Heap property of the parent-child relationship being bigger or smaller, it bubbles up to its right position. Similarly, removing is also O of log N because it removes the elements and then bubbles down to restore the Heap property. And since heaps are actually balanced binary trees, which more on that later, both insertion and deletion operations are extremely efficient compared to linear data structures like arrays or linked lists which we talked about.
Data Structure #6: Hashmap
The next data structure we’re going to talk about is the Hashmap and make sure you know this one.
Think of a Hashmap like a mail room in an office where every employee has a dedicated mailbox. Instead of sorting through all the mail one by one by one, you just look, “Oh, John, his mailbox is number four. Sally, her mailbox is number five.” You know exactly where to put it and John and Sally know exactly where to access it. A Hashmap stores data using key-value pairs where each key is run through a hash function that determines where the value should be stored. An example of a hash function could be the length of a string. So John’s name, for example, is four characters long, so he’s in position four. Sally is in position five, her name is five characters long. This makes lookups on hashmaps extremely efficient time complexity wise, being O of one.
However, if too many items hash to the same mailbox, which we call a hash collision, for example, if a new employee Andy joins, well, his name is also four letters, we can’t just put him in position number four because that’s where John is. So we need to have a hash collision resolution, which could be a linked list chaining from the hashmap position, or it could be linear probing where you find the next available position. Either way, this is the only real downside to hashmaps. Otherwise, they are super, super efficient as a data structure.
Hashmap Time Complexities
So overall, accessing an element by its key in a hashmap is an O of one operation, but it could be O of N worst case if everything is put onto that linked list and you have to do a lot of searching. Inserting an element is an O of one operation, but worst case scenario that could end up being O of N. Deleting an element is also an O of one operation because if you have the right key, you can just go to the value, but if there is a long linked list that you have to deal with to find the actual element that you’re dealing with, that could end up being an O of N operation. By the way, if you use Python, you probably call hashmaps dictionaries, but they’re pretty much the same thing.
Data Structure #7: Binary Search Tree
The next data structure we’re going to talk about is the binary search tree.
So it’s a tree, it looks similar to a family tree, but the key difference is each node follows a specific ordering rule: the left child has to contain values smaller than the parent and the right child has to contain values greater than the parent. This makes searching, insertion, and deletion extremely efficient.
Binary Search Tree Time Complexities
In terms of the Big O, accessing, inserting, and deleting into a binary search tree is an O of log N procedure because of the rules of the left parent and right needing to be less than one another while we’re dealing with the elements. Every time we look to access an element, insert an element, or delete an element, you can literally eliminate half the tree as we’re going through it, so it’s like going through the dictionary trying to find that word because you’re just splitting up your search space by half every layer that you’re going.
But worst case, if your binary search tree is unbalanced for some reason and it looks something similar to a linked list, each of those operations, access, insertion, and deletion, becomes O of N because you might have to go through each element, there’s no elimination of search space.
Data Structure #8: Sets
The next data structure we’re going to talk about is the set.
And I want you to think of this like Thanos’s Infinity Gauntlet. It can hold powerful stones, but each stone is unique. If Thanos tries to add the same stone twice, it simply won’t work because the gauntlet can only allow one of each kind. Also, the order in which he collects the stones doesn’t matter at all, as long as like he has all the stones in whatever order, they’re all unique, it’ll be good. Sets are very useful if you’re searching through trees or you’re searching through graphs and you want to keep track of if you visited a certain node or not.
And overall, the definition of a set is an unordered collection of unique elements, typically implemented using a hash table, similarly the efficiency of a hash map with the hash function. This makes checking for the existence of an element extremely fast, which means O of one on average time. However, similar to all the issues that we had with the hash function and the hashmaps causing potential collisions, that can take it all the way up to O of N. Unlike arrays or linked lists, sets don’t store duplicates and they don’t maintain a specific order. And in fact, they’re actually used for a lot of coding interview questions such as removing duplicates from a linked list, removing duplicates from a data set, or checking for a certain membership or performing mathematical set operations. So make sure you know your sets because it’s never going to be the main data structure, but it’s always going to be something to have in handy just like Thanos’s Gauntlet.
Set Time Complexities
In terms of the Big O time complexity, inserting and deleting are going to be O of one operations because of the whole hash function, but if there’s so many hash collisions, once again, it’s going to be O of N worst case, just like it was for the hashmap. And that’s if the case is it’s run by hash tables in the background, there are various other ways to create sets. I just gave you an example of a hash set.
Conclusion
And if you’re interested in leveling up your career, applying your data structures knowledge to actual LeetCode problems that show up in top tech interviews for companies like Amazon or Google, you might want to check out my newsletter down below where I’m going to send you guys links for popular LeetCode problems by each company for different data structures so you guys can practice and really get ahead of the game.
Well, that’s about all I have in this article. I really hope that you guys enjoyed it and if you did, make sure to hit the like button, subscribe if you haven’t already. And now, if you’re interested in landing a software engineering internship for summer of 2025, check out this article right here.