Interview at Company Y
Here are the questions asked during my interview at Company Y. It was a mix of rapid-fire technical questions (QCM style) and a deeper problem-solving discussion.
Part 1: Technical Concepts (QCM & short answers)
1. Static Variables and Class State
Question: What does g() return?
class MyClass {
static int i;
static void f() { i = i - 1; }
static int g() {
i = 2;
f();
return i;
}
}
Answer: 1.
Reason: i is static, so it’s shared. i becomes 2, then f() decrements it to 1.
2. Arrays vs Hash Sets – Complexity
Question: Which statement is true regarding space complexity? Answer: Both hash sets and arrays have O(N) space complexity. Reason: To store N elements, both need linear space relative to N.
3. Bubble Sort Complexity
Question: Time required to sort a list of n elements using Bubble Sort? Answer: O(n²) (Average and Worst Case).
4. Design Patterns
Question: A pattern where a composite object contains a collection of the same interface and delegates operations to children? Answer: Composite Pattern. Key Idea: Treat individual objects and compositions of objects uniformly.
5. Set Data Structure
Question: What is a Set, when to use it, and give a simple example? Answer:
- Definition: A collection of unique elements (no duplicates).
- Use Case: When you need to ensure uniqueness or perform fast lookups ($O(1)$) to check existence.
- Example: Storing unique visitor IP addresses to count distinct users.
6. Data Structure Selection
Question: You have characters and need to store them in the exact order of the message. No uniqueness required. What structure? Answer: List (or Array / Vector). Reason: Sets do not preserve insertion order (typically) and do not allow duplicates. A List/Vector is ordered and allows duplicates.
7. Method Overloading vs Overriding
Question: Difference between Overloading and Overriding? Answer:
- Overloading: Same method name, different parameters (compile-time polymorphism).
- Overriding: Same method signature in a subclass (runtime polymorphism).
8. Dynamic Dispatch in C++
Question: Explain dynamic dispatch in C++ in detail. Answer:
- It’s the mechanism to select which implementation of a polymorphic operation (virtual function) to call at runtime.
- V-Table (Virtual Table): The compiler creates a static table for each class containing function pointers to virtual methods.
- V-Ptr (Virtual Pointer): Each object instance has a hidden pointer (
vptr) pointing to its class’s V-Table. - Runtime: When calling
obj->method(), the program follows thevptrto the V-Table, looks up the function address, and calls it.
9. Access Modifiers (Cross-Package Inheritance)
Question: Class B inherits from Class A (different package). Can B access A’s public, protected, private members via an instance of A passed as a parameter?
Answer:
a.myPublic: YES.a.myProtected: NO. (Protected members are accessible in subclasses via inheritance, but not via object references of the parent class from a different package).a.myPrivate: NO.
10. Static Methods & Instance State
Statement: “Static methods don’t belong to objects — they can’t see instance state.”
Verdict: TRUE.
Reason: Static methods belong to the class. They do not have a this pointer, so they cannot access non-static fields (this.variable) or methods.
11. Exception Handling (Java vs C++)
Question: Which statements are true?
NullPointerExceptionis unchecked? TRUE.- Checked exceptions must be handled at compile-time (Java)? TRUE.
- C++ does exception handling at compile-time? FALSE (C++ exceptions are unchecked).
ClassNotFoundExceptionis unchecked? FALSE (It is Checked).- Both handled with try-catch-finally? TRUE.
12. Java Thread Creation
Question: How can a thread be created in Java? Answer:
- Extend
Threadclass:class MyThread extends Thread { public void run() { ... } } - Implement
Runnableinterface:class MyRunnable implements Runnable { public void run() { ... } }(Better practice). - Modern way: Use
ExecutorService/CompletableFuture.
13. Multithreading: C++ vs Java
Question: Comparison? Answer:
- Java: Built-in
Threadclass, JVM manages stack/memory,synchronizedkeyword for locks, robust memory model. - C++:
std::thread(since C++11), manual memory management (danger of accessing freed memory), constructs likestd::mutex,std::unique_lock. Lower level, higher control, higher risk.
14. Rust Thread Creation
Question: How is a thread created in Rust?
Answer:
Using std::thread::spawn.
use std::thread;
thread::spawn(move || {
// code
});
- Note: The
movekeyword is often used to transfer ownership of capturing variables into the new thread.
15. C++ Lambda Syntax
Question: Explain C++ Lambda syntax.
Answer:
[capture](parameters) -> return_type { body }
[]: No capture.[=]: Capture all by value.[&]: Capture all by reference.(): Arguments.{}: Function body.
16. C++ RAII & Stack Unwinding
Question: Output of this code?
struct Foo { /* ... throws in raise() ... */ };
int main() { try { Foo f; f.raise(); } catch(...) { /* ... */ } }
Answer: Construct, Raise, Destroy, Catch, Bye!
Reason: When raise() throws, Stack Unwinding begins. The destructor ~Foo() is called before control enters the catch block. This is the core of RAII (Resource Acquisition Is Initialization).
17. C++ Temporary Object Lifetime
Question: What happens here?
const char* data = get_data().c_str(); // get_data() returns std::string by value
std::cout << data;
Answer: Undefined Behavior (Dangling Pointer).
Reason: get_data() returns a temporary std::string. c_str() gets a pointer to its internal buffer. At the end of the line (semicolon), the temporary string is destroyed, freeing the memory. data now points to garbage.
Fix: std::string s = get_data(); std::cout << s.c_str();
Part 2: Problem Solving (Complexity Analysis)
Question: Algorithm Complexity Analysis
Determine the Time Complexity of the following algorithm:
// x is the input size
for (int i = 4; i < x; i++) {
for (int k = 0; k < ((x * x) / 2); k++) {
// Constant time data processing
}
}
Answer: O(x³)
Step-by-Step Analysis
To find the time complexity, we need to count how many times the inner body executes. We can use the Multiplication Rule because the loops are nested.
1. Analyze the Outer Loop (i)
- Start:
i = 4 - End:
i < x - Increment:
i++(Step of 1) - Iterations: The loop runs from 4 to x - 1.
- Total iterations $\approx x - 4$.
- In Big-O notation, we drop lower-order constants, so this is O(x).
2. Analyze the Inner Loop (k)
- Start:
k = 0 - End:
k < (x * x) / 2 - Iterations: The loop runs from 0 to $\frac{x^2}{2} - 1$.
- Dependency: This loop runs completely for every single iteration of the outer loop.
- Total iterations $\approx \frac{x^2}{2}$.
- In Big-O notation:
- We ignore coefficients (like $\frac{1}{2}$).
- We conclude this loop is O(x²).
3. Combine (Multiplication Rule) Since the loops are nested (the inner loop runs fully for each step of the outer loop), we multiply their complexities:
$$ \text{Total Complexity} = O(\text{Outer Loop}) \times O(\text{Inner Loop}) $$
$$ \text{Total Complexity} = O(x) \times O(x^2) $$
$$ \text{Total Complexity} = O(x^3) $$
Conclusion
The algorithm has a Cubic Time Complexity, or O(x³).
Interview Tip: When analyzing nested loops:
- Ignore constants (starting at 4 or dividing by 2 doesn’t change the growth rate).
- Identify the relationship between the loops (Nested = Multiply, Sequential = Add).
- Focus on the dominant term. $x \times x^2 = x^3$.