Discover the top 80+ C++ interview questions, ranging from basic to advanced, vital for freshers and experienced professionals to succeed in programming roles.
OVERVIEW
C++ is a robust general-purpose programming language that combines the efficiency of low-level programming with the adaptability of high-level languages. Developed in the early 1980s, it is renowned for its object-oriented features and is widely used in system software, game development, and high-performance computing.
Learning C++ interview questions are vital for anyone looking to excel in software development roles. Familiarity with these questions helps you grasp essential concepts and prepares you for the real-world challenges you may encounter in the industry.
By mastering C++ interview questions, candidates can effectively showcase their problem-solving abilities, boosting their confidence and improving their chances of success in the competitive job market.
Download C++ Interview Questions
Note : We have compiled all C++ Interview Questions for you in a template format. Feel free to comment on it. Check it out now!
Here are some essential C++ interview questions for freshers. These questions cover the fundamental concepts of C++ development, assess knowledge of object-oriented programming, data structures, and memory management, and provide insights into how well candidates understand the building blocks of C++ programming and software development.
C++ is a general-purpose, high-level programming language used for system and application development. Developed by Bjarne Stroustrup at Bell Labs in 1983, it builds upon the C language while introducing object-oriented features. It supports multiple paradigms, including procedural, functional, and generic programming. This is one of the most commonly asked C++ interview questions.
Below are some of the advantages of C++:
C++ has numerous applications, which are frequently highlighted in C++ interview questions.
Major software companies and tech giants use C++ for various applications, including:
In C++ interview questions, one common topic is the different data types available. C++ data types are broadly classified into three categories:
Selecting the appropriate data type depends on the needs of the application, as data types define both the size and kind of values to be stored.
In this set of fresher-level C++ interview questions, one frequently encountered question is about references. Declaring a variable as a reference provides an alternate name for an existing variable.
A reference variable is created by placing an ‘&’ in the declaration. Essentially, a reference acts as an alias for another variable, allowing access to the associated variable through either its original name or the reference itself.
Syntax:
dataType& referenceName = existingVariable;
Using references facilitates easier manipulation of variables without copying their values, making them particularly useful in function parameters and return types.
A common topic that often appears in C++ interview questions is the difference between call by value and call by reference.
In this set of fresher-level C++ interview questions, one common topic is the concept of namespaces. Namespaces in C++ are used to organize multiple classes and functions, which simplifies application management. To access a class or function from a specific namespace, the syntax namespacename::classname is employed.
The most commonly used namespace in C++ is the std namespace, which contains components of the standard library. Programmers can also create custom namespaces to encapsulate related functionality, helping to avoid name clashes in larger projects.
To access elements within a namespace, you can utilize the scope resolution operator (::) or the using directive.
For instance, std::cout refers to the cout object in the std namespace. Alternatively, using namespace std; allows for the direct use of cout without needing the prefix. Nested namespaces can also be created to establish hierarchical organizations of code. Additionally, anonymous namespaces provide internal linkage, making identifiers visible only within the same translation unit.
In C++ interview questions, one frequently asked question is about operator overloading. Operator overloading is a form of compile-time polymorphism that allows operators to be given special meanings for user-defined data types.
This feature enables most operators to be redefined or overloaded to perform operations on these user-defined types. For instance, C++ allows the addition of variables of user-defined data types in a manner similar to built-in data types.
Note : Run tests across 3000+ real devices, browsers, and OS combinations. Try LambdaTest Now!
The primary difference between C and C++ is that C is a function-based procedural language without object and class support, whereas C++ combines procedural programming with object-oriented features.
Feature | C | C++ |
---|---|---|
Paradigm | Procedural | Multi-paradigm (OOP, procedural, generic). |
Focus | System Programming | General-purpose programming. |
Data and functions | Separate | It can be encapsulated (classes). |
Function overloading | Not supported | Supported |
Default arguments | Not supported | Supported |
References | Not available | Available |
Exception handling | Not supported | Supported |
Inheritance | Not supported | Supported |
Polymorphism | Not supported | Supported |
Standard library | Smaller | Extensive (STL) |
Memory management | Manual (malloc/free). | Both manual and automatic (new/delete). |
Namespace | Not supported | Supported |
Operator overloading | Not supported | Supported |
Input/Output | printf/scanf | cin/cout (also supports C-style). |
Typecasting | Implicit and explicit | More controlled (static_cast, etc.). |
In this set of fresher-level C++ interview questions, a common topic in C++ is the concept of templates.
Templates in C++ are essential for generic programming, serving as blueprints for creating generic classes or functions. In simple terms, templates enable developers to design a single function or class that can work with various data types.
C++ templates, often called generic functions or classes, are a powerful feature of the language. The keyword "template" defines the syntax, while the angled brackets containing a parameter (e.g., T) specify the data type variable.
There are two main types of templates in C++:
A function in C++ is a collection of statements designed to accept input, perform specific computations, and produce output. The primary purpose of a function is to group tasks that are frequently executed, which helps avoid code duplication. Instead of rewriting the same code for different inputs, you can simply call the function.
In essence, a function is a block of code that executes only when it is invoked.
In this set of fresher-level C++ interview questions, a common topic often asked is the concept of a destructor.
A destructor is an instance member function that gets called automatically whenever an object is about to be destroyed. This means that a destructor is the last function that will be executed before an object is removed from memory.
It has the same name as the class, prefixed with a tilde (~), and does not take arguments. Their function is to deallocate memory or resources associated with the object.
Syntax:
class ClassName {
public:
// Constructor
ClassName() {
// Constructor code
}
// Destructor
~ClassName() {
// Destructor code
}
};
In the context of C++, a common topic that appears in C++ interview questions is function overloading.
Function overloading in C++ refers to the process of having two or more functions with the same name but differing in parameters. This can involve using different types of arguments or a varying number of arguments. The compiler differentiates between the functions based on these distinctions.
The primary benefit of function overloading is that it enhances the readability of the program, allowing developers to use the same function name for similar actions without needing to come up with different names.
In this set of fresher-level C++ interview questions, a common question often asked is about the Standard Template Library (STL).
The C++ Standard Template Library (STL) is a collection of template classes and functions that provides implementations of common data structures and algorithms, including lists, stacks, arrays, sorting, searching, and more. Additionally, it supplies iterators and functions, making it easier to work with algorithms and containers. The STL enhances code reusability and efficiency, allowing developers to focus on higher-level programming tasks.
Type conversion, also known as type casting, refers to the process of converting one data type into another within a program. This can be done in two ways: automatically by the compiler or manually by the programmer.
In this set of fresher-level C++ interview questions, a common topic that often appears is type conversion. It’s essential to understand the two types of type conversion:
bool -> char -> short int -> int -> unsigned int -> long -> unsigned long -> long long -> float -> double -> long double
In C++, streams are defined as sequences of characters that flow between the program and input/output (I/O) devices. The C++ stream classes provide functionalities for handling input and output operations with files and other I/O devices, making it easier to create portable code that functions on multiple platforms.
C++ has a total of 95 reserved keywords. These keywords possess special meanings and cannot be redefined or overloaded. Some examples include const_cast, new, struct, and using.
In this set of fresher-level C++ interview questions, a common question often asked is about iostream.
Iostream stands for standard input-output stream. Including #include <iostream> allows for the declaration of objects that handle reading from and writing to standard streams. Essentially, the iostream library functions as an object-oriented library that facilitates input and output operations through the use of streams.
A stream can be defined as a sequence of bytes and is regarded as an abstraction of a device. This abstraction allows for the execution of I/O operations on the device. It is necessary to include the iostream header file to perform input and output tasks in a C++ program.
Syntax:
#include <iostream>
Whitespace refers to the characters used for formatting in C++. It mainly consists of spaces, tabs, and newlines. The primary uses of whitespace in C++ are to separate various language components, format text, and improve code layout.
Operators that cannot be overloaded in C++ include:
#include<bits/stdc++.h> is used to include every standard library in C++.
In this set of C++ interview questions, a common topic is the distinction between references and pointers.
Below are the table highlights the key differences between a reference and a pointer:
Characteristic | Reference | Pointer |
---|---|---|
Declaration | Uses & operator | Uses * operator |
Initialization | It must be initialized at declaration. | It can be initialized later. |
Nullability | It cannot be null | Can be null |
Memory | Doesn't occupy additional memory. | Occupies memory to store the address. |
Ease of use | Generally easier and safer. | More flexible but prone to errors if not careful. |
Performance | Typically optimized by the compiler. | It may have slight overhead due to indirection. |
In this set of C++ interview questions, understanding exception handling is crucial for developers.
Exceptions are defined as runtime anomalies or abnormal conditions that a program encounters while executing. The method of handling these exceptions is known as exception handling. Through this mechanism, control can be transferred from the section of the program where the exception occurred to another part of the code.
The main components of exception handling in C++ are:
Syntax:
try {
// Code that may throw an exception
if (some_error_condition) {
throw some_exception;
}
} catch (exception_type e) {
// Handle the exception
}
A default argument refers to a value specified in the function declaration that the compiler automatically assigns if the calling function does not pass any value to that argument.
The basic syntax for a function with default arguments looks like this:
return_type function_name(type1 param1, type2 param2 = default_value2, type3 param3 = default_value3) {
// Function body
}
Default arguments are useful for several reasons:
An exception refers to an unexpected problem that arises during the execution of a program, often causing it to terminate abruptly. Exceptions occur at runtime, meaning they happen while the program is running rather than during compilation.
In C++, exceptions are classified into two types:
In this set of fresher-level C++ interview questions, one common question asked is about the differences between C++ and Java. Below is a table highlighting the primary differences:
There are many differences and similarities between the C++ and Java programming languages. Below is the table of the primary differences between C++ and Java:
Feature | C++ | Java |
---|---|---|
Memory Management | Manual (supports pointers). | Automatic (garbage collection). |
Platform Independence | Platform-dependent | Write once, run anywhere (WORA). |
Multiple Inheritance | Supports multiple inheritance. | Supports multiple interface inheritance only. |
Operator Overloading | Supported | Not supported (except for + for strings). |
Standard Template Library (STL) | Includes STL | Has Java API (different from STL). |
Global Variables | Supports global variables. | Does not support global variables. |
A stack is a container that stores elements in a last-in, first-out (LIFO) sequence. It is implemented as a container adaptor, which is a class that utilizes another container class as its underlying container. The underlying container can be a vector, deque, or list. If no specific container is mentioned when creating a stack instance, the default underlying container used is deque.
Conio stands for Console-Input-Output and refers to the conio.h header file, a non-standard file used in C and C++ programming. It contains functions related to console input/output and is mainly utilized by MS-DOS compilers.
In this set of fresher-level C++ interview questions, a common topic that is often asked about is expressions in C++.
Expressions consist of variables, constants, and operators organized according to the syntax rules of the language. They may also include function calls that return values. An expression can have one or more operands and zero or more operators to compute a result. Each expression generates a value, which is then assigned to a variable using an assignment operator.
Example of different types of expressions are:
A + 5 // Arithmetic expression
A > B && C <= D // Logical expression combining relational expressions
++i // Increment expression (with side effect)
func(A, B) // Function call expression
A ? B : C // Conditional expression
Below are some of the best C++ compilers:
A function prototype is a declaration that informs the program about the number and type of parameters, as well as the type of value that the function will return. One highly beneficial feature of C++ functions, often asked in C++ interview questions, is function prototyping.
A function prototype conveys essential information, such as the number and type of parameters and the return value type, to clarify the function interface for the compiler.
Syntax:
return_type function_name(parameter_list);
The endl is a predefined object of the ostream class. It is utilized to insert newline characters and flush the output stream.
Syntax:
std::cout << "Hello, World!" << std::endl;
An iterator is an object that acts like a pointer, pointing to elements inside a container and allowing traversal through its contents. Iterators enable access to data within containers and connect algorithms with data manipulation.
The most basic form of an iterator is a pointer, which can iterate through array elements using the increment operator (++). However, not all iterators function like pointers.
In this set of C++ interview questions, the concept of the double colon (::) is often discussed.
Known as the scope resolution operator, the double colon is used for several purposes:
This operator helps clarify variable scopes and enhances code organization.
An enum, short for enumeration, is a user-defined data type that can be assigned a specific set of limited values. The programmer defines these values during the declaration of the enumerated type.
The C++ interview questions discussed above are crucial for any fresher, as they provide a foundational understanding of key concepts and practices in C++ programming. Mastering these fundamentals is essential for building a strong skill set and excelling in interviews.
As you progress, you will encounter intermediate-level C++ interview questions that will deepen your knowledge and expertise. This advancement will prepare you to tackle more complex topics and scenarios, ultimately enhancing your skills in C++ programming and contributing effectively within the software development field.
Download C++ Interview Questions
Note : We have compiled all C++ Interview Questions for you in a template format. Feel free to comment on it. Check it out now!
Here are some intermediate-level C++ interview questions designed for experienced developers. These questions delve into more advanced topics in C++ programming, including memory management, object-oriented concepts, and modern C++ features.
In this set of C++ interview questions, a common question asked in C++ is about vectors. A vector is a sequence container class that implements a dynamic array, meaning its size automatically adjusts when elements are appended. It stores elements in contiguous memory locations and allocates memory as necessary during runtime.
To use vectors, the <vector> header must be included in a C++ program. Vectors provide various member functions for operations such as adding elements (push_back), removing elements (pop_back), accessing elements (using array-like indexing or the at() function), and querying the size of the vector.
Below is an example using a vector to store a list of programming languages:
#include <iostream>
#include <vector>
#include <string>
int main() {
std::vector<std::string> programmingLanguages;
programmingLanguages.push_back("C++");
programmingLanguages.push_back("Python");
programmingLanguages.push_back("JavaScript");
std::cout << "Programming Languages: ";
for (const std::string& language : programmingLanguages) {
std::cout << language << " ";
}
std::cout << std::endl;
std::cout << "Total number of programming languages: " << programmingLanguages.size() << std::endl;
return 0;
}
In this set of C++ interview questions, it's important to understand how vectors differ from arrays. Firstly, vectors are dynamic in size, meaning they can grow or shrink as needed during runtime. In contrast, arrays have a fixed size determined at compile time and cannot be changed.
Vectors provide built-in bounds checking through the at() function, which throws an exception if you try to access an out-of-range element. Arrays lack this safety feature, making them more prone to buffer overflow errors.
Another primary difference is memory management. Vectors automatically handle memory allocation and deallocation, while arrays require manual memory management, particularly when using dynamically allocated arrays.
In this set of C++ interview questions, you may be asked how to sort a vector. The elements of a vector can be sorted efficiently using the std::sort() function from the STL's algorithm library.
This function requires iterators that specify the vector's start and endpoints. It arranges the elements in ascending order by default, but this behavior can be customized with a user-defined comparator.
Below is a sample code that sorts a vector of programming languages based on their popularity scores in ascending order:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct ProgrammingLanguage {
string name;
int popularityScore;
ProgrammingLanguage(string n, int p) : name(n), popularityScore(p) {}
};
void displayLanguages(const vector<ProgrammingLanguage>& languages) {
for (const ProgrammingLanguage& lang : languages) {
cout << lang.name << ": " << lang.popularityScore << endl;
}
}
int main() {
vector<ProgrammingLanguage> languages = {
ProgrammingLanguage("C++", 100),
ProgrammingLanguage("Python", 90),
ProgrammingLanguage("Java", 85),
ProgrammingLanguage("JavaScript", 95),
ProgrammingLanguage("C#", 80)
};
cout << "Unsorted Programming Languages: " << endl;
displayLanguages(languages);
sort(languages.begin(), languages.end(), [](const ProgrammingLanguage& a, const ProgrammingLanguage& b) {
return a.popularityScore < b.popularityScore;
});
cout << "
Sorted Programming Languages by Popularity in Ascending Order: " << endl;
displayLanguages(languages);
return 0;
}
Output:
Unsorted Programming Languages:
C++: 100
Python: 90
Java: 85
JavaScript: 95
C#: 80
Sorted Programming Languages by Popularity in Ascending Order:
C#: 80
Java: 85
Python: 90
JavaScript: 95
C++: 100
In this set of C++ interview questions, you may also encounter the concept of a pure virtual function.
A pure virtual function, also referred to as an abstract function in C++, is a virtual function that can have an implementation but must be overridden in any derived class; failing to do so will result in the derived class also being classified as an abstract class. A pure virtual function is declared by assigning a value of 0 in its declaration.
Here’s an example of pure virtual functions in C++:
class AbstractTest {
public:
virtual void display() = 0; // Pure virtual function
};
A map in C++ is an associative container that stores key-value pairs. It's part of the Standard Template Library (STL) and is defined in the <map> header. Maps are implemented as balanced binary search trees, which provide efficient lookup, insertion, and deletion operations.
In this set of C++ interview questions, you may be asked how to empty a vector.
To achieve this, use the clear() method. This method removes all elements from the vector, effectively setting its size to zero while keeping its capacity unchanged.
Below is an example demonstrating how to clear a vector containing a list of programming languages:
#include <iostream>
#include <vector>
#include <string>
int main() {
std::vector<std::string> languages = {"C++", "Python", "JavaScript", "Go"};
std::cout << "Languages before clearing: ";
for (const auto& lang : languages) {
std::cout << lang << " ";
}
std::cout << std::endl;
languages.clear();
std::cout << "Languages after clearing: ";
for (const auto& lang : languages) {
std::cout << lang << " ";
}
std::cout << std::endl;
return 0;
}
Output:
Languages before clearing: C++ Python JavaScript Go
Languages after clearing:
To address segmentation faults in C++, consider the following strategies:
In this set of C++ interview questions, you may come across the concept of buffer flush.
A buffer flush refers to the process of transferring data from a temporary storage area to the computer's permanent memory. For example, when modifications are made to a file, the visible changes on the screen are temporarily held in a buffer.
Generally, a temporary file is created when a Word document is opened and is automatically deleted when the main file is closed. Therefore, when the work is saved, any changes made since the last save are flushed from the buffer to permanent storage on the hard disk.
In C++, it is possible to explicitly flush the buffer to ensure the data is written. The std::endl function performs a similar role by inserting a newline character and flushing the stream. The output stream stdout/cout is line-buffered, meaning the output is not sent to the operating system until a new line is written or the buffer is explicitly flushed.
A friend function is a function that is declared with the friend keyword inside a class but defined outside of it. This function has access to the class’s private and protected members, which can be useful for operations that require intimate access to a class’s internals but are logically better placed outside the class. This is one of the most frequently asked questions in C++ interview questions.
This is one of the most frequently asked questions in C++ interview questions; the size of an empty class is often tricky.
While an empty class contains no data members or member functions, it still occupies some memory. The C++ standard mandates that each object must have a unique address, and thus, compilers usually allocate 1 byte of memory for an empty class.
However, when used as a base class, the empty class might not contribute to the size of the derived class, thanks to the "empty base optimization." The exact size can be checked using the sizeof operator, which typically returns 1 for an empty class.
In this set of C++ interview questions, the concept of the bool data type is commonly asked. The bool is a fundamental data type used to represent boolean values, which are essential for controlling program flow and decision-making.
A boolean value in C++ can either be true or false and is commonly used in conditional statements, loops, and control structures to check whether a condition is met. This allows for clear and effective decision-making in programs.
Object-Oriented Programming (OOPs) is a frequently asked topic. OOPs is a programming paradigm in C++ that revolves around objects, which are instances of classes. It organizes software design by focusing on data (objects) rather than logic or functions.
The four main principles of OOPs in C++ are:
These principles allow for modular, reusable, and maintainable code. This question is often asked in most of the C++ interview questions.
Understanding constructors and destructors is crucial. A constructor is a member function of a class that has the same name as the class and is used to initialize objects. It is automatically called when an instance of a class is created. Constructors can take parameters and can be overloaded, but they are not inherited.
A destructor, on the other hand, is a special function that has the same name as the class, preceded by a tilde (~). It is called automatically when an object goes out of scope or is deleted and is used to free resources or perform cleanup.
Below is a table comparing the primary differences between constructor and destructor:
Characteristic | Constructor | Destructor |
---|---|---|
Purpose | Initializes objects and sets initial values. | Cleans up resources and performs necessary deletions. |
Naming | Same name as the class. | Class name preceded by tilde (~). |
When called | Automatically, when the object is created. | Automatically, when the object goes out of scope or is deleted. |
Number Allowed | Multiple (can be overloaded). | Only one per class. |
Parameters | It can take parameters. | It cannot take parameters. |
Inheritance | Not inherited | Inherited |
Explicit call | It can be called explicitly (rare). | It cannot be called explicitly. |
Memory allocation | Often used to allocate memory. | Often used to deallocate memory. |
This comparison has often been asked in most of the C++ interview questions.
Inheritance is an essential concept often covered in C++ interview questions. It allows a class to inherit properties and behaviors (methods) from another class. This feature promotes code reuse and simplifies the creation of complex systems.
There are four types of inheritance in C++:
Encapsulation is a key topic in C++ and is often asked in most C++ interview questions as it refers to the concept of bundling data (variables) and methods (functions) into a single unit, typically a class. It restricts direct access to some of the class’s components, protecting the internal state from unwanted interference and misuse.
Key aspects of encapsulation include:
Abstraction is another fundamental concept in C++ topics and it has often been asked in most of the C++ interview questions.
It refers to the process of hiding complex implementation details and exposing only the necessary parts of an object or class. It allows programmers to work with higher-level concepts without worrying about the intricate details behind the scenes. Abstraction simplifies the development process by focusing on what an object does rather than how it achieves that functionality.
The this pointer in C++ is a special pointer that points to the current object instance. This concept is often featured in C++ interview questions, as this pointer is implicitly passed to all non-static member functions.
It is used to differentiate between class members and parameters with the same name, return the current object from a member function, pass the current object as a parameter to other functions, and implement chaining of function calls.
A common question to be asked in most of the C++ interview questions is about the difference between std::vector and std::array.
The primary difference is that a vector is a sequential container that can dynamically store elements but is not strictly fixed in size, while an array is a fixed-size sequential collection of elements of the same type that is strictly index-based.
Below are the key differences include:
Characteristic | std::vector | std::array |
---|---|---|
Size | Dynamic size | Fixed-size |
Memory allocation | Dynamic (heap) | Static (stack) |
Resizing | Can be resized | It cannot be resized |
Performance | Slightly slower due to dynamic allocation. | Faster due to stack allocation. |
Initialization | It can be initialized with any number of elements. | Must specify size at compile time. |
Use case | When size is unknown at compile time. | When size is known at compile time. |
Standard | Since C++98 | Since C++11 |
Character constants, also known as character literals, are often discussed in C++ interview questions. They are one or more members of the source character set enclosed in single quotation marks ('). In C++, a character literal consists of a single constant character.
There are two types of character literals:
Static data members and static member functions are commonly featured in C++ interview questions. Static data members are class members declared with the static keyword, and they share a single instance across all class objects.
In contrast, static member functions are functions declared as static within a class, allowing them to be called without creating an instance of the class. However, these functions do not have access to instance variables or non-static member functions.
The volatile keyword in C++ is often asked in most of the C++ interview questions. It informs the compiler that the value of a variable declared with volatile can change unexpectedly at any moment. Additionally, it prevents the compiler from optimizing the code, which is primarily useful for memory-mapped hardware, signal handlers, and machine code instructions.
C++ Storage Classes are commonly covered in C++ interview questions as they define the attributes of a variable or function, including its lifetime and visibility. The main storage classes include automatic, static, register, external, and mutable.
Understanding the difference between shallow copy and deep copy is important, and has often been asked in most of the C++ interview questions.
A shallow copy duplicates data by copying pointers and references, meaning both the original and the copied object will reference the same underlying data.
In contrast, a deep copy creates an entirely separate copy of the underlying data, ensuring that the original and copied objects do not share any data.
Characteristic | Shallow Copy | Deep Copy |
---|---|---|
Definition | Copies object's memory address. | Creates a new object with copied content. |
Pointer handling | Copies pointer addresses. | Creates new objects for pointed-to data. |
Memory allocation | No new memory was allocated. | New memory is allocated for copied data. |
Independence | The copied object shares data with the original. | The copied object is independent of the original. |
Performance | Faster and less memory-intensive | Slower and more memory-intensive |
Use case | When sharing data is intended. | When independent copies are needed. |
Complexity | Simpler to implement. | More complex to implement. |
Suitable for | Simple data types shared resources. | Objects with dynamic memory and unique resources. |
The concept of block scope variables is often asked in most of the C++ interview questions. A block-scoped variable, also known as a local variable, is declared within a function or a block (like loops or conditional statements). It can only be accessed within the specific function or block where it was defined, remaining inaccessible outside that block.
The intermediate-level C++ interview questions outlined above are designed to help both beginners and those with some experience effectively prepare for interviews.
As you progress in your C++ journey, you will encounter more complex questions specifically aimed at experienced developers. These questions will deepen your understanding and mastery of various C++ concepts, ensuring you're well-equipped to tackle the challenges of software development in the industry.
In addition to theoretical knowledge, practical coding skills are crucial for excelling in C++ interviews. It’s essential to understand the nuances of C++ syntax, memory management, and object-oriented principles.
Here are some programming questions often asked in C++ interview questions that focus on practical coding challenges. These questions are designed to assess your problem-solving skills and your ability to write efficient code in C++.
This program reverses a string using a recursive approach. In the example given, the string "Recursion" is reversed to "noisruceR," demonstrating the effective use of recursion for string manipulation.
#include <iostream>
#include <string>
using namespace std;
void reverseRecursively(string& str, int start, int end) {
if (start >= end)
return;
swap(str[start], str[end]);
reverseRecursively(str, start + 1, end - 1);
}
int main() {
string str = "Recursion";
reverseRecursively(str, 0, str.length() - 1);
cout << "Reversed String: " << str << endl;
return 0;
}
This program calculates the factorial of a given non-negative integer using an iterative approach. In the example, if the user inputs 5, the output will be a factorial of 5 is 120, demonstrating the successful calculation of the factorial.
#include <iostream>
int factorialIterative(int n) {
if (n < 0) {
throw std::invalid_argument("Negative numbers do not have factorials.");
}
int result = 1;
for (int i = 1; i <= n; ++i) {
result *= i;
}
return result;
}
int main() {
int number;
std::cout << "Enter a number: ";
std::cin >> number;
try {
int result = factorialIterative(number);
std::cout << "Factorial of " << number << " is " << result << std::endl;
} catch (const std::invalid_argument& e) {
std::cout << e.what() << std::endl;
}
return 0;
}
This program generates the Fibonacci sequence up to N numbers using a dynamic programming approach. In the example, when N is set to 10, the output displays the first ten Fibonacci numbers: 0 1 1 2 3 5 8 13 21 34, effectively illustrating the growth of the sequence.
#include <iostream>
#include <vector>
std::vector<int> fibonacciDynamic(int N) {
std::vector<int> fibSequence(N, 0);
if (N <= 0) return fibSequence;
if (N >= 1) fibSequence[0] = 0;
if (N >= 2) fibSequence[1] = 1;
for (int i = 2; i < N; ++i) {
fibSequence[i] = fibSequence[i - 1] + fibSequence[i - 2];
}
return fibSequence;
}
int main() {
int N = 10;
std::vector<int> result = fibonacciDynamic(N);
for (int num : result) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
This program checks if a number is prime using a recursive function. The function evaluates whether the number is divisible by any integer starting from 2.
If the divisor squared exceeds the number, it returns true, indicating that the number is prime. In the example, the number 29 is checked and confirmed to be a prime number, as it is only divisible by 1 and itself.
#include <iostream>
bool isPrimeRecursive(int n, int divisor = 2) {
if (n <= 1) return false;
if (divisor * divisor > n) return true;
if (n % divisor == 0) return false;
return isPrimeRecursive(n, divisor + 1);
}
int main() {
int num = 29;
if (isPrimeRecursive(num)) {
std::cout << num << " is a prime number." << std::endl;
} else {
std::cout << num << " is not a prime number." << std::endl;
}
return 0;
}
This program uses a binary search algorithm to find a target element's lower and upper bounds in a sorted array. By narrowing the search space with each iteration, it efficiently identifies the indices of the target's first and last occurrences.
For example, the array {1, 2, 2, 3, 4, 5, 6, 7, 8, 9} determines that the target 2 is found between indices 1 and 2.
#include <iostream>
#include <vector>
std::pair<int, int> findBounds(const std::vector<int>& arr, int target) {
int left = 0;
int right = arr.size() - 1;
int lower = -1, upper = -1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] == target) {
lower = mid;
right = mid - 1;
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
left = 0;
right = arr.size() - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] == target) {
upper = mid;
left = mid + 1;
} else if (arr[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
return {lower, upper};
}
int main() {
std::vector<int> arr = {1, 2, 2, 3, 4, 5, 6, 7, 8, 9};
int target = 2;
auto [lower, upper] = findBounds(arr, target);
if (lower != -1 && upper != -1) {
std::cout << "Element found between indices " << lower << " and " << upper << std::endl;
} else {
std::cout << "Element not found" << std::endl;
}
return 0;
}
This program finds the largest and smallest numbers in an array using the C++ Standard Library's max_element and min_element functions. In the provided example, the array {12, 4, 7, 9, 15, 2, 8} yields 15 as the largest number and 2 as the smallest.
This approach showcases the utility of built-in functions for common tasks in array manipulation, ensuring concise and readable code.
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> arr = {12, 4, 7, 9, 15, 2, 8};
auto largest = *std::max_element(arr.begin(), arr.end());
auto smallest = *std::min_element(arr.begin(), arr.end());
std::cout << "Largest number: " << largest << std::endl;
std::cout << "Smallest number: " << smallest << std::endl;
return 0;
}
This program implements the Bubble Sort algorithm, which sorts an array by repeatedly stepping through the list, comparing adjacent elements, and swapping them if they are in the wrong order. The process is repeated until the array is sorted.
In the provided example, the unsorted array {64, 34, 25, 12, 22, 11, 90} is sorted into {11, 12, 22, 25, 34, 64, 90}. This demonstrates the basic functionality of the Bubble Sort algorithm, highlighting its simple logic and ease of implementation.
#include <iostream>
#include <vector>
void bubbleSortBasic(std::vector<int>& arr) {
int n = arr.size();
for (int i = 0; i < n - 1; ++i) {
for (int j = 0; j < n - i - 1; ++j) {
if (arr[j] > arr[j + 1]) {
// Swap arr[j] and arr[j + 1]
std::swap(arr[j], arr[j + 1]);
}
}
}
}
int main() {
std::vector<int> arr = {64, 34, 25, 12, 22, 11, 90};
bubbleSortBasic(arr);
std::cout << "Sorted array: ";
for (int num : arr) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
This program removes duplicates from a sorted array using the std::unique function from the C++ Standard Library. In the example, the sorted array {1, 1, 2, 2, 3, 4, 4, 5} is transformed into {1, 2, 3, 4, 5}, effectively handling duplicates in a sorted dataset.
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> arr = {1, 1, 2, 2, 3, 4, 4, 5};
auto last = std::unique(arr.begin(), arr.end());
arr.erase(last, arr.end());
std::cout << "Array after removing duplicates: ";
for (int num : arr) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
This program calculates the greatest common divisor (GCD) of two numbers using the Euclidean algorithm. In the example given, the GCD of 56 and 98 is computed and displayed.
#include <iostream>
int gcdEuclidean(int a, int b) {
while (b != 0) {
int temp = b;
b = a % b;
a = temp;
}
return a;
}
int main() {
int a = 56;
int b = 98;
std::cout << "GCD of " << a << " and " << b << " is " << gcdEuclidean(a, b) << std::endl;
return 0;
}
This program converts a decimal number to its binary representation using bitwise operations. In the example provided, the decimal number 29 is converted and displayed in binary format.
#include <iostream>
void decimalToBinaryBitwise(int n) {
if (n == 0) {
std::cout << "0";
return;
}
unsigned int mask = 1 << (sizeof(int) * 8 - 1);
bool leadingZero = true;
for (int i = 0; i < sizeof(int) * 8; ++i) {
if ((n & mask) != 0) {
std::cout << "1";
leadingZero = false;
} else if (!leadingZero) {
std::cout << "0";
}
mask >>= 1;
}
}
int main() {
int decimalNumber = 29;
std::cout << "Binary representation: ";
decimalToBinaryBitwise(decimalNumber);
std::cout << std::endl;
return 0;
}
This program implements a stack using an array to manage a collection of integers with last-in-first-out (LIFO) behavior.
It provides essential stack operations, including push to add elements, pop to remove the top element, and peek to view the top element without removing it.
#include <iostream>
#define MAX 100
class Stack {
private:
int arr[MAX];
int top;
public:
Stack() {
top = -1;
}
void push(int x) {
if (isFull()) {
std::cout << "Stack overflow
";
return;
}
arr[++top] = x;
std::cout << x << " pushed to stack
";
}
void pop() {
if (isEmpty()) {
std::cout << "Stack underflow
";
return;
}
std::cout << arr[top--] << " popped from stack
";
}
int peek() {
if (isEmpty()) {
std::cout << "Stack is empty
";
return -1;
}
return arr[top];
}
bool isEmpty() {
return top == -1;
}
bool isFull() {
return top == MAX - 1;
}
};
int main() {
Stack stack;
stack.push(10);
stack.push(20);
stack.push(30);
stack.push(40);
std::cout << stack.peek() << " is at the top of the stack
";
stack.pop();
stack.pop();
std::cout << stack.peek() << " is at the top of the stack
";
return 0;
}
This program determines whether two strings are anagrams by comparing the frequency of their characters.
#include <iostream>
#include <string>
#include <unordered_map>
#include <algorithm>
bool checkAnagram(const std::string& text1, const std::string& text2) {
std::string temp1 = text1;
std::string temp2 = text2;
temp1.erase(std::remove(temp1.begin(), temp1.end(), ' '), temp1.end());
temp2.erase(std::remove(temp2.begin(), temp2.end(), ' '), temp2.end());
std::transform(temp1.begin(), temp1.end(), temp1.begin(), ::tolower);
std::transform(temp2.begin(), temp2.end(), temp2.begin(), ::tolower);
if (temp1.size() != temp2.size()) {
return false;
}
std::unordered_map<char, int> charFrequency;
for (char ch : temp1) {
charFrequency[ch]++;
}
for (char ch : temp2) {
if (charFrequency.find(ch) == charFrequency.end() || charFrequency[ch] == 0) {
return false;
}
charFrequency[ch]--;
}
for (const auto& entry : charFrequency) {
if (entry.second != 0) {
return false;
}
}
return true;
}
int main() {
std::string input1 = "Night";
std::string input2 = "Thing";
if (checkAnagram(input1, input2)) {
std::cout << """ << input1 << "" and "" << input2 << "" are anagrams." << std::endl;
} else {
std::cout << """ << input1 << "" and "" << input2 << "" are not anagrams." << std::endl;
}
return 0;
}
This program implements a queue using a linked list to provide fundamental queue operations such as enqueue, dequeue, isEmpty, and peek. It efficiently manages adding and removing elements from the queue, demonstrating the FIFO (First-In-First-Out) principle inherent to queue data structures.
#include <iostream>
class Node {
public:
int data;
Node* next;
Node(int value) : data(value), next(nullptr) {}
};
class Queue {
private:
Node* front;
Node* rear;
public:
Queue() : front(nullptr), rear(nullptr) {}
void enqueue(int value) {
Node* newNode = new Node(value);
if (rear) {
rear->next = newNode;
}
rear = newNode;
if (!front) {
front = rear;
}
std::cout << value << " enqueued to queue
";
}
void dequeue() {
if (isEmpty()) {
std::cout << "Queue is empty
";
return;
}
Node* temp = front;
std::cout << front->data << " dequeued from queue
";
front = front->next;
if (!front) {
rear = nullptr;
}
delete temp;
}
int peek() {
if (isEmpty()) {
std::cout << "Queue is empty
";
return -1;
}
return front->data;
}
bool isEmpty() {
return front == nullptr;
}
~Queue() {
while (!isEmpty()) {
dequeue();
}
}
};
int main() {
Queue queue;
queue.enqueue(10);
queue.enqueue(20);
queue.enqueue(30);
std::cout << queue.peek() << " is at the front of the queue
";
queue.dequeue();
queue.dequeue();
std::cout << queue.peek() << " is at the front of the queue
";
return 0;
}
This program reverses a linked list by updating the next pointers of each node. It uses an iterative approach using three-pointers, prev, curr, and next, to navigate and modify the links. This technique demonstrates efficient manipulation of pointers in a linked data structure.
#include <iostream>
class Node {
public:
int data;
Node* next;
Node(int value) : data(value), next(nullptr) {}
};
class LinkedList {
private:
Node* head;
public:
LinkedList() : head(nullptr) {}
void append(int value) {
Node* newNode = new Node(value);
if (!head) {
head = newNode;
} else {
Node* temp = head;
while (temp->next) {
temp = temp->next;
}
temp->next = newNode;
}
}
void reverse() {
Node* prev = nullptr;
Node* curr = head;
Node* next = nullptr;
while (curr) {
next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
head = prev; }
void display() const {
Node* temp = head;
while (temp) {
std::cout << temp->data << " -> ";
temp = temp->next;
}
std::cout << "nullptr" << std::endl;
}
~LinkedList() {
while (head) {
Node* temp = head;
head = head->next;
delete temp;
}
}
};
int main() {
LinkedList list;
list.append(10);
list.append(20);
list.append(30);
list.append(40);
std::cout << "Original list: ";
list.display();
list.reverse();
std::cout << "Reversed list: ";
list.display();
return 0;
}
This program finds the middle element of a linked list using the two-pointer technique. A slow pointer moves one step at a time, while a fast pointer moves two steps. When the fast pointer reaches the end, the slow pointer will be in the middle of the list. If the list is empty, an error message is displayed.
#include <iostream>
class Node {
public:
int data;
Node* next;
Node(int value) : data(value), next(nullptr) {}
};
class LinkedList {
private:
Node* head;
public:
LinkedList() : head(nullptr) {}
void append(int value) {
Node* newNode = new Node(value);
if (!head) {
head = newNode;
} else {
Node* temp = head;
while (temp->next) {
temp = temp->next;
}
temp->next = newNode;
}
}
int findMiddle() {
if (!head) {
std::cerr << "List is empty
";
return -1;
}
Node* slow = head;
Node* fast = head;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
}
return slow->data;
}
void display() const {
Node* temp = head;
while (temp) {
std::cout << temp->data << " -> ";
temp = temp->next;
}
std::cout << "nullptr" << std::endl;
}
~LinkedList() {
while (head) {
Node* temp = head;
head = head->next;
delete temp;
}
}
};
int main() {
LinkedList list;
list.append(10);
list.append(20);
list.append(30);
list.append(40);
list.append(50);
std::cout << "List: ";
list.display();
int middle = list.findMiddle();
if (middle != -1) {
std::cout << "Middle element: " << middle << std::endl;
}
return 0;
}
This program detects a cycle in a linked list using a hash set to track visited nodes. It allows appending new nodes and can create a cycle at a specified position.
#include <iostream>
#include <unordered_set>
class Node {
public:
int data;
Node* next;
Node(int value) : data(value), next(nullptr) {}
};
class LinkedList {
private:
Node* head;
public:
LinkedList() : head(nullptr) {}
void append(int value) {
Node* newNode = new Node(value);
if (!head) {
head = newNode;
} else {
Node* temp = head;
while (temp->next) {
temp = temp->next;
}
temp->next = newNode;
}
}
void createCycle(int position) {
if (position < 0) return;
Node* cycleStart = nullptr;
Node* temp = head;
int index = 0;
while (temp && temp->next) {
if (index == position) {
cycleStart = temp;
}
temp = temp->next;
index++;
}
if (temp && cycleStart) {
temp->next = cycleStart;
}
}
bool hasCycle() {
std::unordered_set<Node*> visitedNodes;
Node* temp = head;
while (temp) {
if (visitedNodes.find(temp) != visitedNodes.end()) {
return true;
}
visitedNodes.insert(temp);
temp = temp->next;
}
return false;
}
void display() const {
Node* temp = head;
while (temp) {
std::cout << temp->data << " -> ";
temp = temp->next;
}
std::cout << "nullptr" << std::endl;
}
~LinkedList() {
while (head) {
Node* temp = head;
head = head->next;
delete temp;
}
}
};
int main() {
LinkedList list;
list.append(10);
list.append(20);
list.append(30);
list.append(40);
list.append(50);
std::cout << "Original list: ";
list.display();
list.createCycle(2);
if (list.hasCycle()) {
std::cout << "Cycle detected in the linked list.
";
} else {
std::cout << "No cycle detected in the linked list.
";
}
return 0;
}
This program implements a binary tree and provides methods for three types of tree traversals: in-order, pre-order, and post-order. It allows users to insert nodes into the tree and then display the nodes in the specified traversal order.
#include <iostream>
class Node {
public:
int data;
Node* left;
Node* right;
Node(int value) : data(value), left(nullptr), right(nullptr) {}
};
class BinaryTree {
private:
Node* root;
void inorderTraversal(Node* node) const {
if (node) {
inorderTraversal(node->left);
std::cout << node->data << " ";
inorderTraversal(node->right);
}
}
void preorderTraversal(Node* node) const {
if (node) {
std::cout << node->data << " ";
preorderTraversal(node->left);
preorderTraversal(node->right);
}
}
void postorderTraversal(Node* node) const {
if (node) {
postorderTraversal(node->left);
postorderTraversal(node->right);
std::cout << node->data << " ";
}
}
public:
BinaryTree() : root(nullptr) {}
void insert(int value) {
if (!root) {
root = new Node(value);
} else {
Node* current = root;
Node* parent = nullptr;
while (true) {
parent = current;
if (value < current->data) {
current = current->left;
if (!current) {
parent->left = new Node(value);
return;
}
} else {
current = current->right;
if (!current) {
parent->right = new Node(value);
return;
}
}
}
}
}
void inorder() const {
std::cout << "In-Order Traversal: ";
inorderTraversal(root);
std::cout << std::endl;
}
void preorder() const {
std::cout << "Pre-Order Traversal: ";
preorderTraversal(root);
std::cout << std::endl;
}
void postorder() const {
std::cout << "Post-Order Traversal: ";
postorderTraversal(root);
std::cout << std::endl;
}
~BinaryTree() {
destroyTree(root);
}
private:
void destroyTree(Node* node) {
if (node) {
destroyTree(node->left);
destroyTree(node->right);
delete node;
}
}
};
int main() {
BinaryTree tree;
tree.insert(50);
tree.insert(30);
tree.insert(70);
tree.insert(20);
tree.insert(40);
tree.insert(60);
tree.insert(80);
tree.inorder();
tree.preorder();
tree.postorder();
return 0;
}
This program calculates the height of a binary tree using an iterative approach based on level-order traversal. It uses a queue to keep track of the nodes at each level and counts the number of levels until all nodes have been processed.
The height of the binary tree is determined by the total number of levels, providing an efficient method to assess its structure.
#include <iostream>
#include <queue>
class Node {
public:
int data;
Node* left;
Node* right;
Node(int value) : data(value), left(nullptr), right(nullptr) {}
};
class BinaryTree {
private:
Node* root;
public:
BinaryTree() : root(nullptr) {}
void insert(int value) {
if (!root) {
root = new Node(value);
} else {
Node* current = root;
Node* parent = nullptr;
while (true) {
parent = current;
if (value < current->data) {
current = current->left;
if (!current) {
parent->left = new Node(value);
return;
}
} else {
current = current->right;
if (!current) {
parent->right = new Node(value);
return;
}
}
}
}
}
int getHeight() const {
if (!root) return 0;
std::queue<Node*> q;
q.push(root);
int height = 0;
while (!q.empty()) {
int nodeCount = q.size();
while (nodeCount > 0) {
Node* node = q.front();
q.pop();
if (node->left) q.push(node->left);
if (node->right) q.push(node->right);
nodeCount--;
}
height++;
}
return height;
}
~BinaryTree() {
destroyTree(root);
}
private:
void destroyTree(Node* node) {
if (node) {
destroyTree(node->left);
destroyTree(node->right);
delete node;
}
}
};
int main() {
BinaryTree tree;
tree.insert(50);
tree.insert(30);
tree.insert(70);
tree.insert(20);
tree.insert(40);
tree.insert(60);
tree.insert(80);
std::cout << "Height of the binary tree: " << tree.getHeight() << std::endl;
return 0;
}
This program checks whether a binary tree is balanced by using a recursive approach to calculate the height of the left and right subtrees for each node. A binary tree is considered balanced if the height difference between the left and right subtrees is no greater than one for all nodes.
#include <iostream>
#include <algorithm>
class Node {
public:
int data;
Node* left;
Node* right;
Node(int value) : data(value), left(nullptr), right(nullptr) {}
};
class BinaryTree {
private:
Node* root;
int checkHeight(Node* node) const {
if (!node) return 0;
int leftHeight = checkHeight(node->left);
if (leftHeight == -1) return -1;
int rightHeight = checkHeight(node->right);
if (rightHeight == -1) return -1;
if (std::abs(leftHeight - rightHeight) > 1) return -1;
return std::max(leftHeight, rightHeight) + 1;
}
public:
BinaryTree() : root(nullptr) {}
void insert(int value) {
if (!root) {
root = new Node(value);
} else {
Node* current = root;
Node* parent = nullptr;
while (true) {
parent = current;
if (value < current->data) {
current = current->left;
if (!current) {
parent->left = new Node(value);
return;
}
} else {
current = current->right;
if (!current) {
parent->right = new Node(value);
return;
}
}
}
}
}
bool isBalanced() const {
return checkHeight(root) != -1;
}
~BinaryTree() {
destroyTree(root);
}
private:
void destroyTree(Node* node) {
if (node) {
destroyTree(node->left);
destroyTree(node->right);
delete node;
}
}
};
int main() {
BinaryTree tree;
tree.insert(50);
tree.insert(30);
tree.insert(70);
tree.insert(20);
tree.insert(40);
tree.insert(60);
tree.insert(80);
if (tree.isBalanced()) {
std::cout << "The binary tree is balanced." << std::endl;
} else {
std::cout << "The binary tree is not balanced." << std::endl;
}
return 0;
}
This program implements a hash table using open addressing with linear probing. It provides functionalities to insert, search, and remove key-value pairs.
The program demonstrates how to handle collisions by probing for the next available slot, ensuring efficient storage and retrieval.
#include <iostream>
#include <vector>
#include <string>
#include <optional>
class HashTable {
private:
std::vector<std::pair<int, std::string>> table;
std::vector<bool> occupied;
int capacity;
int hashFunction(int key) const {
return key % capacity;
}
int probe(int index) const {
int i = 0;
while (occupied[(index + i) % capacity]) {
i++;
}
return (index + i) % capacity;
}
public:
HashTable(int size) : capacity(size), table(size, { -1, "" }), occupied(size, false) {}
void insert(int key, const std::string& value) {
int index = hashFunction(key);
int pos = probe(index);
table[pos] = { key, value };
occupied[pos] = true;
}
bool search(int key, std::string& value) const {
int index = hashFunction(key);
int pos = index;
int i = 0;
while (occupied[pos]) {
if (table[pos].first == key) {
value = table[pos].second;
return true;
}
i++;
pos = (index + i) % capacity;
}
return false;
}
void remove(int key) {
int index = hashFunction(key);
int pos = index;
int i = 0;
while (occupied[pos]) {
if (table[pos].first == key) {
occupied[pos] = false;
return;
}
i++;
pos = (index + i) % capacity;
}
}
void display() const {
for (int i = 0; i < capacity; ++i) {
if (occupied[i]) {
std::cout << "Index " << i << ": (" << table[i].first << ", " << table[i].second << ")" << std::endl;
} else {
std::cout << "Index " << i << ": Empty" << std::endl;
}
}
}
};
int main() {
HashTable hashTable(10);
hashTable.insert(1, "One");
hashTable.insert(2, "Two");
hashTable.insert(12, "Twelve");
hashTable.insert(22, "Twenty Two");
std::string value;
if (hashTable.search(12, value)) {
std::cout << "Key 12 found with value: " << value << std::endl;
} else {
std::cout << "Key 12 not found." << std::endl;
}
hashTable.remove(12);
if (hashTable.search(12, value)) {
std::cout << "Key 12 found with value: " << value << std::endl;
} else {
std::cout << "Key 12 not found." << std::endl;
}
hashTable.display();
return 0;
}
This program uses recursion and memoization to find the longest common subsequence of two strings. It efficiently computes the longest sequence of characters that appears in both strings while maintaining their order.
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
int lcsRecursive(const std::string& s1, const std::string& s2, int m, int n, std::vector<std::vector<int>>& memo) {
if (m == 0 || n == 0) return 0;
if (memo[m][n] != -1) return memo[m][n];
if (s1[m - 1] == s2[n - 1]) {
memo[m][n] = 1 + lcsRecursive(s1, s2, m - 1, n - 1, memo);
} else {
memo[m][n] = std::max(lcsRecursive(s1, s2, m - 1, n, memo), lcsRecursive(s1, s2, m, n - 1, memo));
}
return memo[m][n];
}
std::string longestCommonSubsequenceRecursive(const std::string& s1, const std::string& s2) {
int m = s1.length();
int n = s2.length();
std::vector<std::vector<int>> memo(m + 1, std::vector<int>(n + 1, -1));
lcsRecursive(s1, s2, m, n, memo);
std::string lcs;
int i = m, j = n;
while (i > 0 && j > 0) {
if (s1[i - 1] == s2[j - 1]) {
lcs.push_back(s1[i - 1]);
--i;
--j;
} else if (memo[i - 1][j] > memo[i][j - 1]) {
--i;
} else {
--j;
}
}
std::reverse(lcs.begin(), lcs.end());
return lcs;
}
int main() {
std::string s1 = "ABCBDAB";
std::string s2 = "BDCAB";
std::string lcs = longestCommonSubsequenceRecursive(s1, s2);
std::cout << "Longest Common Subsequence: " << lcs << std::endl;
return 0;
}
To solve the N-Queens problem, backtracking is used to place queens on an N×N chessboard one column at a time. The algorithm checks each row for a safe position using a utility function to ensure that no two queens threaten each other.
Additional arrays track which columns and diagonals are under attack, optimizing placement by reducing the number of necessary checks.
#include <iostream>
using namespace std;
#define N 4
int leftDiagonal[30] = {0};
int rightDiagonal[30] = {0};
int column[30] = {0};
void printSolution(int board[N][N]) {
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
cout << (board[i][j] ? "Q " : ". ");
}
cout << endl;
}
}
bool solveNQUtil(int board[N][N], int col) {
if (col >= N) return true;
for (int i = 0; i < N; i++) {
if (!leftDiagonal[i - col + N - 1] && !rightDiagonal[i + col] && !column[i]) {
board[i][col] = 1;
leftDiagonal[i - col + N - 1] = rightDiagonal[i + col] = column[i] = 1;
if (solveNQUtil(board, col + 1)) return true;
board[i][col] = 0;
leftDiagonal[i - col + N - 1] = rightDiagonal[i + col] = column[i] = 0;
}
}
return false;
}
bool solveNQ() {
int board[N][N] = {0};
if (!solveNQUtil(board, 0)) {
cout << "Solution does not exist" << endl;
return false;
}
printSolution(board);
return true;
}
int main() {
solveNQ();
return 0;
}
Preparing for C++ interviews is crucial for anyone pursuing a career in software development. The collection of these top 80+ C++ Interview Questions and Answers aims to assist candidates of all levels in enhancing their knowledge and skills.
By practicing these questions, candidates can deepen their understanding of C++ and its core concepts. With thorough preparation, job seekers can effectively demonstrate their proficiency in C++, significantly improving their chances of success in securing desired roles within the tech industry.
Download C++ Interview Questions
Note : We have compiled all C++ Interview Questions for you in a template format. Feel free to comment on it. Check it out now!
Did you find this page helpful?
Try LambdaTest Now !!
Get 100 minutes of automation test minutes FREE!!