InterviewStack.io LogoInterviewStack.io

Data Structures and Complexity Questions

Comprehensive coverage of fundamental data structures, their operations, implementation trade offs, and algorithmic uses. Candidates should know arrays and strings including dynamic array amortized behavior and memory layout differences, linked lists, stacks, queues, hash tables and collision handling, sets, trees including binary search trees and balanced trees, tries, heaps as priority queues, and graph representations such as adjacency lists and adjacency matrices. Understand typical operations and costs for access, insertion, deletion, lookup, and traversal and be able to analyze asymptotic time and auxiliary space complexity using Big O notation including constant, logarithmic, linear, linearithmic, quadratic, and exponential classes as well as average case, worst case, and amortized behaviors. Be able to read code or pseudocode and derive time and space complexity, identify performance bottlenecks, and propose alternative data structures or algorithmic approaches to improve performance. Know common algorithmic patterns that interact with these structures such as traversal strategies, searching and sorting, two pointer and sliding window techniques, divide and conquer, recursion, dynamic programming, greedy methods, and priority processing, and when to combine structures for efficiency for example using a heap with a hash map for index tracking. Implementation focused skills include writing or partially implementing core operations, discussing language specific considerations such as contiguous versus non contiguous memory and pointer or manual memory management when applicable, and explaining space time trade offs and cache or memory behavior. Interview expectations vary by level from selecting and implementing appropriate structures for routine problems at junior levels to optimizing naive solutions, designing custom structures for constraints, and reasoning about amortized, average case, and concurrency implications at senior levels.

EasyTechnical
81 practiced
In Kotlin, implement a generic Stack<T> class using an internal array (do not use ArrayDeque). Provide push, pop, peek, size, and isEmpty. Ensure push has amortized O(1) time. Describe your growth strategy and explain complexity for push and pop. You can ignore concurrency and serialization concerns. Example signature:
class ArrayStack<T> { // implement}
EasyTechnical
99 practiced
Compare adjacency list and adjacency matrix representations for graphs. For a mobile app that processes social-graph data of up to 50k users with average degree 10, which representation would you choose and why? Discuss time/space trade-offs and cache/IO considerations for queries like "friends-of-friends" or short-path computations.
MediumTechnical
91 practiced
Given a sorted IntArray in Kotlin, implement twoSumSorted(nums: IntArray, target: Int): IntArray that returns 1-based indices of two numbers adding to target. Aim for O(n) time and O(1) extra space. The array may be large (n up to 1e6). Provide code and explain why two-pointer is preferred over a hash map on memory-constrained mobile devices.
EasyTechnical
75 practiced
Explain the amortized time complexity of append on dynamic arrays (e.g., Java ArrayList, Kotlin MutableList, Swift Array). Why is append considered amortized O(1)? Compare growth factors (2x vs 1.5x) and their effects on memory spikes and total copies. For a mobile app that frequently appends many small elements, what strategies reduce allocation spikes and GC/ARC churn?
HardTechnical
91 practiced
Analyze the following pseudocode used for shortest-path in an offline mapping feature. Compute worst-case time and space complexity assuming adjacency lists. Propose mobile optimizations (graph representation, lazy loading tiles, heuristics) and name advanced techniques (A*, contraction hierarchies) to speed up queries.
function shortestPath(src, dst, graph): dist = map(); prev = map(); for v in graph.vertices: dist[v] = INF dist[src] = 0 pq = MinHeap() pq.push((0, src)) while pq not empty: (d, u) = pq.pop() for edge in graph.adj[u]: if dist[edge.v] > d + edge.w: dist[edge.v] = d+edge.w; pq.push((dist[edge.v], edge.v)) return dist[dst]

Unlock Full Question Bank

Get access to hundreds of Data Structures and Complexity interview questions and detailed answers.

Sign in to Continue

Join thousands of developers preparing for their dream job.