Data Structures Coding Interview 90+ Chapters
Data Structures Coding Interview 90+ Chapters
Introduction
Sorting Algorithms:
Searching Algorithm
Data structure tutorial 1: Stack Data structure and Implementation using arrays.
Data structure tutorial 2: Stack Data structure and Implementation using Linked List.
Data structure tutorial 3: Singly Linked List.
Data structure tutorial 4: Doubly Linked List [DLL] .
Data structure tutorial 5: Circular Singly Linked List.
Data structure tutorial 6: Circular Doubly Linked List.
Data structure tutorial 7: Queue Data Structure with implementation using arrays.
Data structure tutorial 8: Queue Data Structure with implementation using linked list.
Data structure tutorial 9: Circular Queues Data structure with Implementation using arrays.
Data structure tutorial 10: Circular Queue Data structure with Implementation using Linked
List.
String matching algorithms tutorial 1. Knuth Morris Pratt String matching algorithm
String matching algorithms tutorial 2. Rabin Karp algorithm
String matching algorithms tutorial 3. Boyer–Moore string-search algorithm
Knapsack Problem:
1. Fractional knapsack
2. Knapsack
Additional Problems:
5.1 Introduction
Quick Sort is a divide and conquer technique. Usually we use Quick Sort on a very large data
set.
Below is a brief on how this algorithm works:
To perform Quick sort, we need the help of “pivot element”. Pivot element holds an
important role in this algorithm.
Then while comparing with the left pointer, we check if the element is less than the pivot
element. If it is less, we do nothing. If the element is greater than the pivot element we
swap the elements.
Similarly, while comparing with the right pointer, we check if the element is greater than the
pivot element. If the element is less than the pivot element, we swap the elements.
By doing the above 2 operations, we make sure that all the elements to the left of pivot
element are less and elements to right of pivot are greater. [Revisit these points once you
go through the example below].
Initially the left pointer will be pointing to left part of the array.
Pivot element also will be pointing to the left part of the array, as shown below:
We know that, all the elements to the right of the pivot element should be greater than the
pivot element and all the elements left of the pivot will be lesser than the pivot element.
Initially, the pivot is at the left, hence we start comparing from the right and move towards
left. To move an element towards left, that element should be less than the pivot element.
Hence we check below condition.
Now that the pivot element is at the right, we start comparing from left and move towards
right. For an element to be at right of pivot element, it should be greater than the pivot
element. hence we check below condition:
Hence we move the left pointer to the next element as shown below:
after comparing:
again check if arr[pilot] > arr[left], if(5 > 2) true. Hence increment left pointer to next index
as shown below:
Now agin, check if arr[pilot] > arr[left], if(5 > 6) false. Hence swap element 5 and 6.
Now check if arr[pilot] < arr[right], if(5 < 6) true. Decrement right pointer as shown below:
Now again check if arr[pilot] < arr[right], if(5 < 3) false. Hence swap pivot element and right
element as shown below:
As the pivot element moved from left to right, we start comparing from left and pivot
element.
check if arr[pilot] > arr[left], if(5 > 3) true. Increment left pointer
again check if arr[pilot] > arr[left], if(5 > 1) true. Increment left pointer.
Now that left and right pointer are pointing at the same element of the array, the element 5
is at the pivot element and is in the sorted position.
All the elements left of 5 are smaller and elements to right are larger than 5 as shown
below:
Again we shave to sort the left part and right part. Again the initial array will be like below:
as the pivot is at left, we compare with right pointer and move towards left.
Hence check if arr[pilot] < arr[right], if(4 < 1) False. Hence swap pivot and right element.
Now check if arr[pilot] > arr[left], if(4 > 1) true. Increment left pointer.
again check if arr[pilot] > arr[left], if(4 > 2) true. Increment left pointer by 1.
again check if arr[pilot] > arr[left], if(4 > 3) true. Increment left pointer by 1.
As both left and right pointer points to the same index, it means that element 4 is at it’s
correct position.
Hence again do the same quick sort for the left sub array “1, ,2 , 3”.
#include<stdio.h>
while(i < j)
{
while(array[i] <= array[pivot] && i < lower_index)
i++;
swap(&array[pivot], &array[j]);
return j;
}
}
int main()
{
int length = 0;
int array[100];
int index = 0;
quick_sort(array, 0, length-1);
print_array(array, length);
1
2
3
4
5
Why do we call it as greedy? Because, as you will see further, we choose the shortest
distance first without considering the fact what there might be more optimized path. Hence,
we find another path with shortest value, we update the result with that value.
The working of Kruskal’s algorithm is very simple and can be understood by 3 simple steps
as given below:
Step 2: a. Start from the edge with smallest weight and connect them together.
1. Before connecting, check if it forms a cycle if it forms a cycle then reject the edge and
go for the net smallest weighted edge.
Step 3: Check if all the vertices are connected. If they are not connected, then repeat step 2
till all the vertices are connected.
Once all the tree vertices are connected to an edge, we get MST.
Note: As you see in Prims algorithm that starts by choosing a root vertex, in Kruskal’s
algorithm we start connecting 2 vertices by choosing least weighted edges.
Next connect nodes “D” and “E”, as they are next minimum
Next connect “A” and F”. Thus connecting all the nodes and forming a MST.
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
struct edge
{
int u, v, w;
};
int parents[MAX+5];
vector <E> graph; // Store the inputted graph (u, v, w).
vector <E> selected_edges; // Store the edges which is selected for the MST from given
graph.
return;
}
make_set(nodes);
edgeCounter++;
if( edgeCounter == nodes-1 )
break;
}
return totalCost;
}
int main()
{
E getEdge;
int nodes, edges;
int u, v, w;
cout<<"Edge "<< i<<endl;
cin >> u >> v >> w;
getEdge.u = u;
getEdge.v = v;
getEdge.w = w;
graph.push_back(getEdge);
}
getchar();
return 0;
}
Kruskal’s algorithm should be used in typical situations (sparse graphs) because it uses
simpler data structures.
In this chapter we shall solve Travelling Salesman Problem with help of dynamic
programming.
Problem statement:
A salesman will start from a parent city and visit all the cities only once and return to parent
city. He has to do it with least cost possible.
Consider the below graph and let the parent city be “a”.
Now let’s write the valid cases where the salesman visits all the cities only once and return
to source city.
Here we have visited “b” 2 times. As you can see from the above valid case, we need to find
a Hamiltonian cycle.
As there can be many routes/cycles, we need to find a path with min cost.
So we shall understand the DP approach with the help of the tree below:
Hence from “a” we can go to “b” “c” and “d”. It can be shown as below:
So above image shows all the possible paths. You need to reach to the source vertex again.
Hence we can further update the tree as below:
Starting from the last path, we go from bottom to top and update the cost taking from cost
table.
Now again we go one level up, and check the value for “b -> c -> d -> a”, as we have
calculated value for “c -> d -> a”, we just need to add that value to the last path. Here with
help of DP table we shall be able to do it efficiently.
Now that we have calculated the value for all 6 paths, at the parent node of “b”, “c”, “d”.
We have 2 values, we need to find min of 2 values.
Take 12.
Hence if the salesman travels the path a -> d -> c -> b -> a, he can visit all the cities only once
and arrive at the initial city with min cost.
#include <vector>
#include <iostream>
#include <limits.h>
using namespace std;
int tsp(const vector<vector<int>>& cities, int pos, int visited, vector<vector<int>>& state)
{
if(visited == ((1 << cities.size()) - 1))
return cities[pos][0];
if(state[pos][visited] != INT_MAX)
return state[pos][visited];
int main()
{
vector<vector<int>> cities = { { 0, 15, 4, 5 },
{ 14, 0, 11, 4 },
{ 5, 21, 0, 8 },
{ 5, 4, 12, 0 }
};
vector<vector<int>> state(cities.size());
Output
minimum: 25