C++ is a popular OOP programming language used across the tech industry. Companies like Microsoft, LinkedIn, Amazon, and PayPal list C++ as their main programming language with others for coding interviews.
Overall, C++ is a must-have skill for modern developers interested in these large companies.
Today, we’ll go through the top 40 C++ coding interview questions used to test C++. By the end, you’ll have the confidence and hands-on experience to approach any C++ interview confidently.
Here’s what we’ll cover today:
Compute the complexity of the following code snippet:
int main(){
int n = 10;
int sum = 0;
float pie = 3.14;
for (int i=1; i<n; i+=3){
cout << pie << endl;
for (int j=1; j<n; j+=2){
sum += 1;
cout << sum << endl;
}
}
}
Solution Explanation
On line 6 in the outer loop, int i=1;
runs once, i<n
; gets executed times and i+=3
is executed
times.
In the inner loop, int j=1;
gets executed times in total. j<n;
executes times and j+=2
gets executed times.
For more information, see our line by line breakdown:
Statement | Number of Executions |
---|---|
int n = 10; |
1 |
int sum = 0; |
1 |
float pie = 3.14; |
1 |
int i=1; |
1 |
i<n; |
+ 1 |
i+=3 |
|
cout << pie << endl; |
|
int j=1; |
|
j<n; |
|
j+=2 |
|
sum += 1; |
|
cout << sum << endl; |
Added together, the runtime complexity is
Now convert this to Big O.
Find the Big O complexity of the following code:
int main() {
int n = 10; //n can be anything
int sum = 0;
float pie = 3.14;
int var = 1;
while (var < n){
cout << pie << endl;
for (int j=0; j<var; j++)
sum+=1;
var*=2;
}
cout<<sum;
}
Solution Explanation
Statement | Number of executions |
---|---|
int n = 10; |
1 |
int sum = 0; |
1 |
float pie = 3.14; |
1 |
int var = 1; |
1 |
while(var < n) |
2 |
cout << pie << endl |
2 |
int j=0; |
2 |
j<var; |
|
j++ |
|
sum+=1; |
|
var*=2; |
2 |
cout<<sum; |
1 |
Runtime complexity: 2
Big O:
Find the Big O complexity of the following code:
for( int i=0; i<array.length; i++){
for(int j=0; j<10000; j++)
{
// some useful work done here.
}
}
Solution Explanation
This is a “gotcha” question that tests if you really understand Big O.
Even if they’re nested, the inner loop’s number of executions is not dependent on the input. It will always execute the same number of times.
A common mistake is to answer . Big O calculates for asymptotic behavior therefore, we remove constants like 10,000.
The correct answer is then .
Find the complexity of the following code:
void averager(int[] A) {float avg = 0.0f;int j, count;for (j = 0; j < A.length; j++) {avg += A[j];}avg = avg / A.length;count = j = 0;do {while (j < A.length && A[j] != avg) {j++;}if (j < A.length) {A[j++] = 0;count++;}} while (j < A.length);}
Solution Explanation
The for
loop from lines 6-8 calculates the average of the contents of the array. It’s complexity is .
The do-while
loop from lines 14-24 is tricky. It may seem that the complexity is because of the nested loops.
In fact ,we have to account for two possibilities.
If the average is a float then the nested while
loop on lines 16-17 will increment the value of the variable j
to the size of the input array. Also, the do-while
condition will become false.
The complexity in this case will be
If the average does appear in the array and the array consists of all the same numbers, then the nested while
loop of lines 16-17 will not run. The if
clause of lines 20-23 will kick-in and increment j
to the size of the array as the outer do-while
loop iterates.
Hence the overall complexity of the snippet is .
Find the Big O complexity of the following code:
int recursiveFun1(int n)
{
if (n <= 0)
return 1;
else
return 1 + recursiveFun1(n-1);
}
int recursiveFun2(int n)
{
if (n <= 0)
return 1;
else
return 1 + recursiveFun2(n-5);
}
int recursiveFun3(int n)
{
if (n <= 0)
return 1;
else
return 1 + recursiveFun3(n/5);
}
void recursiveFun4(int n, int m, int o)
{
if (n <= 0)
{
printf("%d, %d\n",m, o);
}
else
{
recursiveFun4(n-1, m+1, o);
recursiveFun4(n-1, m, o+1);
}
}
int recursiveFun5(int n)
{
for (i = 0; i < n; i += 2) {
// do something
}
if (n <= 0)
return 1;
else
return 1 + recursiveFun5(n-5);
}
Solution
For this one, it’s best to break down the problem function by function.
int recursiveFun1(int n)
{
if (n <= 0)
return 1;
else
return 1 + recursiveFun1(n-1);
}
This function is called n
times before reaching base case. It therefore has a Big O complexity of .
int recursiveFun2(int n)
{
if (n <= 0)
return 1;
else
return 1 + recursiveFun2(n-5);
}
This function is called n-5
times and simplifies to with Big O.
int recursiveFun3(int n)
{
if (n <= 0)
return 1;
else
return 1 + recursiveFun3(n/5);
}
The complexity here is because of every time we divide by 5 before calling the function.
void recursiveFun4(int n, int m, int o)
{
if (n <= 0)
{
printf("%d, %d\n",m, o);
}
else
{
recursiveFun4(n-1, m+1, o);
recursiveFun4(n-1, m, o+1);
}
}
Here the complexity is because each function calls itself twice unless recurred n
times.
int recursiveFun5(int n)
{
for (i = 0; i < n; i += 2) {
// do something
}
if (n <= 0)
return 1;
else
return 1 + recursiveFun5(n-5);
}
Finally, the for
loop executes times because i
iterates by 2 and the recursion takes since the loop is called recursively.
Together, they have a complexity of or .
Problem statement:
“Given three integer arrays sorted in ascending order, return the smallest number that is common in all three arrays. Return -1 if there is no common number.”
Hints:
Solution and Breakdown
int find_least_common_number(vector<int>& arr1, vector<int>& arr2, vector<int>& arr3) {int i = 0, j = 0, k = 0;while(i < arr1.size() && j < arr2.size() && k < arr3.size()) {// Finding the smallest common numberif((arr1[i] == arr2[j]) && (arr2[j] == arr3[k]))return arr1[i];// Let's increment the iterator// for the smallest value.if(arr1[i] <= arr2[j] && arr1[i] <= arr3[k]) {i++;}else if(arr2[j] <= arr1[i] && arr2[j] <= arr3[k]) {j++;}else if(arr3[k] <= arr1[i] && arr3[k] <= arr2[j]) {k++;}}return -1;}int main(int argc, char* argv[]) {vector<int> v1 = {6, 7, 10, 25, 30, 63, 64};vector<int> v2 = {1, 4, 5, 6, 7, 8, 50};vector<int> v3 = {1, 6, 10, 14};int result = find_least_common_number(v1, v2, v3);cout << "Least Common Number: " <<result;}
Time complexity:
We use three iterators simultaneously to traverse each of the arrays. Each pointer starts at the 0th index because that is the smallest in the list.
The program first looks to see if the 0th element is shared. Then, we’ll return that value.
Otherwise, we’ll see which iterator amongst the three points to the smallest value and will increment that iterator so that it will point to the next index. We have found the solution when all iterators match.
If any of the three iterators reaches the end of the array before its finds a common number, we’ll return -1.
Problem Statement
“Given an integer array, move all elements that are 0 to the left while maintaining the order of other elements in the array. The array must be modified in-place.”
Hints:
Solution and Breakdown
void move_zeros_to_left(int A[], int n) {if (n < 1) return;int write_index = n - 1;int read_index = n - 1;while(read_index >= 0) {if(A[read_index] != 0) {A[write_index] = A[read_index];write_index--;}read_index--;}while(write_index >= 0) {A[write_index] = 0;write_index--;}}int main() {int v[] = {1, 10, 20, 0, 59, 63, 0, 88, 0};int n = sizeof(v) / sizeof(v[0]);cout << "Original Array" <<endl;for(int x=0 ; x<n; x++) {cout << v[x];cout << ", ";}move_zeros_to_left(v, n);cout << endl<< "After Moving Zeroes to Left"<< endl;for(int i=0 ; i<n; i++) {cout << v[i];cout << ", ";}}
Time complexity:
We keep two markers: read_index
and write_index
. Both start pointed to the end of the array.
While moving read_index
towards the start of the array:
If read_index
points to 0, we that skip element.
If read_index
points to a non-zero value, we write the value at read_index
to the write_index
and then decrement write_index
.
Once read_index
reaches the end of the array, we assign zeros based on the location of write_index
. Any values on or before write_index
must be zeros.
Problem Statement
“Given a singly linked list, reverse the nodes at even indices (starting at 1).”
Hint:
Solution and breakdown
// Helper function to merge two lists.LinkedListNode* merge_alternating(LinkedListNode* list1, LinkedListNode* list2) {if (list1 == nullptr) {return list2;}if (list2 == nullptr) {return list1;}LinkedListNode* head = list1;while (list1->next != nullptr && list2 != nullptr) {LinkedListNode* temp = list2;list2 = list2->next;temp->next = list1->next;list1->next = temp;list1 = temp->next;}if (list1->next == nullptr) {list1->next = list2;}return head;}LinkedListNode* reverse_even_nodes(LinkedListNode* head) {// Let's extract even nodes from the existing// list and create a new list consisting of// even nodes. We will push the even nodes at// head since we want them to be in reverse order.LinkedListNode* curr = head;LinkedListNode* list_even = nullptr;while (curr != nullptr && curr->next != nullptr) {LinkedListNode* even = curr->next;curr->next = even->next;// Push at the head of new list.even->next = list_even;list_even = even;curr = curr->next;}// Now, merge the two lists// Original: 1,2,3,4,5// Modified original: 1,3,5// List_even: 4,2// Merged: 1,4,3,2,5return merge_alternating(head, list_even);}int main() {vector<int> v1 = {7, 14, 21, 28, 9};LinkedListNode* list_head = LinkedList::create_linked_list(v1);cout << "Original list: ";LinkedList::display(list_head);list_head = reverse_even_nodes(list_head);cout <<"After reversing even nodes: ";LinkedList::display(list_head);}
Time Complexity:
We will create two lists comprising of nodes at even and odd indices.
We avoid copying data of elements or reallocating memory to improve efficiency.
We push extracted nodes to the head of list_even
to reverse their order while merging.
Once the two lists are in the correct order, we merge their nodes alternately to create our solution.
Problem Statement
“Given the head pointer of a linked sort, sort the linked list in ascending order using merge sort, and return the new head pointer of sorted linked list.”
Hint:
Solution and Breakdown
typedef LinkedListNode* node_ptr;// this method splits linked list in two halves by iterating over whole list// It returns head pointers of first and 2nd halves of linked lists in first_second// Head of 1st half is just the head node of linked listvoid split_in_half(node_ptr head, pair<node_ptr, node_ptr>& first_second) {if (head == nullptr) {return;}// Only one element in the list.if (head->next == nullptr) {first_second.first = head;first_second.second = nullptr;} else {// Let's use the classic technique of moving two pointers:// 'fast' and 'slow'. 'fast' will move two steps in each// iteration where 'slow' will be pointing to middle element// at the end of loop.node_ptr slow, fast;slow = head;fast = head->next;while (fast != nullptr) {fast = fast->next;if (fast != nullptr) {fast = fast->next;slow = slow->next;}}first_second.first = head;first_second.second = slow->next;// Terminate first linked list.slow->next = nullptr;}}node_ptr merge_sorted_lists(node_ptr first, node_ptr second) {if (first == nullptr) {return second;}else if (second == nullptr) {return first;}node_ptr new_head;if (first->data <= second->data) {new_head = first;first = first->next;}else {new_head = second;second = second->next;}node_ptr new_current = new_head;while (first != nullptr && second != nullptr) {node_ptr temp = nullptr;if (first->data <= second->data) {temp = first;first = first->next;} else {temp = second;second = second->next;}new_current->next = temp;new_current = temp;}if (first != nullptr) {new_current->next = first;} else if (second != nullptr) {new_current->next = second;}return new_head;}node_ptr merge_sort(node_ptr head) {// No need to sort a single element.if (head == nullptr || head->next == nullptr) {return head;}// Let's split the list in half, sort the sublists// and then merge the sorted lists.pair<node_ptr,node_ptr> first_second;split_in_half(head, first_second);first_second.first = merge_sort(first_second.first);first_second.second = merge_sort(first_second.second);return merge_sorted_lists(first_second.first, first_second.second);}int main() {vector<int> v1 = {29, 23, 82, 11, 4, 3, 21};node_ptr list_head_1 = LinkedList::create_linked_list(v1);cout << "Unsorted list: ";LinkedList::display(list_head_1);list_head_1 = merge_sort(list_head_1);cout<<"Sorted list: ";LinkedList::display(list_head_1);}
Time Complexity:
Mergesort is a commonly asked for in interviews. First, you divide the list into smaller lists, then sort each smaller list, and finally combine the sorted lists.
In the dividing step, we split our input linked list in half until there is a linked list of size 1 or 0. Linked lists of size 1 and 0 are always sorted.
In the combining step, we merge sorted lists until we have a completely sorted list.
Problem Statement
“Find the total number of palindromic substrings within a given string.”
Hint:
Solution and Breakdown
#include <bits/stdc++.h>using namespace std;// Function to print a substring// str[low..high]void printSubStr(string str, int low, int high){for (int i = low; i <= high; ++i)cout << str[i];}// This function prints the// longest palindrome substring// It also returns the length of// the longest palindromeint longestPalSubstr(string str){// get length of input stringint n = str.size();// table[i][j] will be false if substring// str[i..j] is not palindrome.// Else table[i][j] will be truebool table[n][n];memset(table, 0, sizeof(table));// All substrings of length 1// are palindromesint maxLength = 1;for (int i = 0; i < n; ++i)table[i][i] = true;// check for sub-string of length 2.int start = 0;for (int i = 0; i < n - 1; ++i) {if (str[i] == str[i + 1]) {table[i][i + 1] = true;start = i;maxLength = 2;}}// Check for lengths greater than 2.// k is length of substringfor (int k = 3; k <= n; ++k) {// Fix the starting indexfor (int i = 0; i < n - k + 1; ++i) {// Get the ending index of substring from// starting index i and length kint j = i + k - 1;// checking for sub-string from ith index to// jth index iff str[i+1] to str[j-1] is a// palindromeif (table[i + 1][j - 1] && str[i] == str[j]) {table[i][j] = true;if (k > maxLength) {start = i;maxLength = k;}}}}cout << "Longest palindrome substring is: ";printSubStr(str, start, start + maxLength - 1);// return length of LPSreturn maxLength;}// Driver Codeint main(){string str = "Galaxy";cout << "\nLength is: "<< longestPalSubstr(str);return 0;}
Time Complexity:
This solution uses a boolean table with a column for each letter. If the X and Y column are the same letter, the table returns that space as true. Otherwise, it returns false.
Here it is step-by-step:
table[n][n]
filled from the bottom up.table[i][j]
is true. Otherwise the value is false.table[i][j]
, we check the value of table[i+1][j-1]
. If the value is true and str[i]
is same as str[j]
, then the substring is a palindrome and we make table[i][j]
true.table[i][j]
is made false.length = 1
and length =2
.Problem Statement
“Reverse the order of words in a given string.”
Hints:
Solution and Breakdown
void str_rev(char *str, int len) {if (str == nullptr || len < 2) {return;}char *start = str;char *end = str + len - 1;while (start < end) {if (start != nullptr && end != nullptr) {char temp = * start;*start = *end;*end = temp;}start++;end--;}}void reverse_words(char *sentence) {// Here sentence is a null-terminated string ending with char '\0'.if (sentence == nullptr) {return;}// To reverse all words in the string, we will first reverse// the string. Now all the words are in the desired location, but// in reverse order: "Hello World" -> "dlroW olleH".int len = strlen(sentence);str_rev(sentence, len);// Now, let's iterate the sentence and reverse each word in place.// "dlroW olleH" -> "World Hello"char *start = sentence;char *end;while (true) {// find the start index of a word while skipping spaces.while (start && *start == ' ') {++start;}if (start == nullptr || *start == '\0') {break;}// find the end index of the word.end = start + 1;while (end && *end != '\0' && *end != ' ') {++end;}// let's reverse the word in-place.if (end != nullptr) {str_rev(start, (end - start));}start = end;}}int main() {string str = "Red Car";char *a = const_cast<char*>(str.c_str());cout << a << endl;reverse_words(a);cout << a << endl;}
Time Complexity:
The program works in two stages:
Stage 2 works by setting a pointer for the beginning of the word, start
, at the on element 0 or the first element after a space.
We also set another pointer for the end of the word, end
, on the element right before the next space.
Both pointers then iterate toward each other, swapping values on each element.
Once the pointers are on the same element, the word has be correctly reversed and our pointers move to the next word.
Our program is complete once all words have been reversed back to their proper order.
Problem Statement
“Implement the function myQueue reverseK(myQueue queue, int k)
which takes a queue and a number k
as input and reverses the first k
elements of the queue.”
Solution and Breakdown
#include "queue.h"#include "stack.h"myQueue reverseK(myQueue queue, int k) {//1.Push first k elements in queue in a stack.//2.Pop Stack elements and enqueue them at the end of queue//3.Dequeue queue elements till "k" and append them at the end of queueif (!queue.isEmpty()) {myStack stack(k);int count = 0;while (count < k) {stack.push(queue.dequeue());count++;}while (!stack.isEmpty()) {queue.enqueue(stack.pop());}int size = queue.getSize();for (int i = 0; i < size - k; i++) {queue.enqueue(queue.dequeue());}}return queue;}int main(){myQueue mQ(5);mQ.enqueue(1);mQ.enqueue(2);mQ.enqueue(3);mQ.enqueue(4);mQ.enqueue(5);mQ=reverseK(mQ,5);mQ.showqueue(); //show queue prepended in the hidden codereturn 0;}
Time Complexity:
First we dequeue the first k
elements from the front of the queue and push them in the stack we created on line 9 with stack.push(queue.dequeue())
.
Once all the k
values have been pushed to the stack, we start popping them and sequentially enqueuing them on line 14. We’ll queue them to the back using queue.enqueue(stack.pop())
. At the end of this step, we will be left with an empty stack and the k
reversed elements will be appended to the back of the queue.
Finally on line 19 we’ll move the resersed elements to the front of the queue usings queue.enqueue(queue.dequeue())
. Each element is first dequeued from the back.
Problem Statement:
"Given a binary tree, populate an array to represent its zigzag level order traversal.
You should populate the values of all nodes of the first level from left to right, then right to left for the next level, alternating in the same way for all levels."
Hints:
Solution and Breakdown
using namespace std;#include <iostream>#include <queue>#include <vector>class TreeNode {public:int val = 0;TreeNode *left;TreeNode *right;TreeNode(int x) {val = x;left = right = nullptr;}};class ZigzagTraversal {public:static vector<vector<int>> traverse(TreeNode *root) {vector<vector<int>> result;if (root == nullptr) {return result;}queue<TreeNode *> queue;queue.push(root);bool leftToRight = true;while (!queue.empty()) {int levelSize = queue.size();vector<int> currentLevel(levelSize);for (int i = 0; i < levelSize; i++) {TreeNode *currentNode = queue.front();queue.pop();// add the node to the current level based on the traverse directionif (leftToRight) {currentLevel[i] = currentNode->val;} else {currentLevel[levelSize - 1 - i] = currentNode->val;}// insert the children of current node in the queueif (currentNode->left != nullptr) {queue.push(currentNode->left);}if (currentNode->right != nullptr) {queue.push(currentNode->right);}}result.push_back(currentLevel);// reverse the traversal directionleftToRight = !leftToRight;}return result;}};int main(int argc, char *argv[]) {TreeNode *root = new TreeNode(12);root->left = new TreeNode(7);root->right = new TreeNode(1);root->left->left = new TreeNode(9);root->right->left = new TreeNode(10);root->right->right = new TreeNode(5);root->right->left->left = new TreeNode(20);root->right->left->right = new TreeNode(17);vector<vector<int>> result = ZigzagTraversal::traverse(root);cout << "Zigzag traversal: ";for (auto vec : result) {for (auto num : vec) {cout << num << " ";}}}
Time Complexity:
root
node to the queue.levelSize
). We will have this many nodes in the current level.levelSize
nodes from the queue and push their value in an array to represent the current level.Problem Statement:
“Create function bool isTree(Graph g)
that takes a graph as input and returns if the passed graph is a tree.”
A graph is a tree if:
- There are no cycles.
- All nodes of the graph are reachable from all other nodes of the graph, directly or through traversal.
Hints:
Solution and Breakdown
#include "Graph.h"using namespace std;bool checkCycle(Graph g,int vertex, bool* visited, int parent){// Mark the current vertex as visitedvisited[vertex] = true;// Recursive calls for all the vertices adjacent to this vertexNode* temp =(g.getArray())[vertex].getHead();while (temp != NULL) {// If an adjacent is not visited, then make recursive call on the adjacentif (!visited[temp->data]) {if(checkCycle(g,temp->data,visited,vertex))return true;}else if (temp->data != parent)return true;//^ If an adjacent is visited and not parent of current// vertex, then there is a cycle.temp = temp->nextElement;}return false;}bool isTree(Graph g){bool *visited = new bool[g.getVertices()];for (int i = 0; i < g.getVertices(); i++)visited[i] = false;if (checkCycle(g,0, visited, -1))return false;for (int i = 0; i < g.getVertices(); i++) {if (!visited[i])return false;