Skip to Content

Programming Interview Questions 2026: Concepts and Code

Programming interview questions cover with a code editor and floating language symbols
Programming interview questions 2026: concepts and code, with examples run in Python.

Highlights

  • What this covers: around 30 real programming interview questions, from Big-O and data structures to OOP, concurrency, and debugging.
  • Format: each answer is what a strong candidate says, plus what the interviewer is really testing.
  • Who it is for: junior to mid-level software engineers and CS or bootcamp grads.
  • Language-agnostic: concepts apply anywhere; examples are in Python for readability.
  • Real measurements: the Big-O and hash-versus-list timings are actual measured output, not claims.
  • How to use it: understand the why behind each idea. Interviewers probe with one follow-up, and that is where memorizers get exposed.

You can build things. You ship features, fix bugs, and your code works. Then an interviewer asks why a hash map lookup is faster than scanning a list, or what actually happens in memory when you pass an object to a function, and you realize that writing code and explaining the machinery under it are two different skills.

That is what programming interviews test. Not whether you can produce working code (they assume that), but whether you understand the fundamentals beneath it: how data structures behave, what an algorithm costs, why one approach scales and another falls over. The questions below are the ones that come up across languages and companies, grouped from the fundamentals you must not fumble to the practical coding and debugging that show how you actually work. Examples are in Python because it reads almost like pseudocode, but the concepts are language-agnostic. Where a snippet has output, that output was really run.

How Programming Interviews Actually Work

Programming interviews come in a few recognizable shapes, often in the same loop.

Fundamentals and trivia. Quick checks: compiled versus interpreted, value versus reference, what Big-O means. One or two clean sentences each.

Data structures and algorithms. The core of most technical screens: pick the right structure, analyze the complexity, and reason about trade-offs. This is where the signal is.

Live coding. Solve a problem in a shared editor while talking through your thinking. They care as much about how you reason and handle edge cases as about the final code.

Practical and behavioral-technical. How you debug, what clean code means to you, how you approach a code review. These reward experience over theory.

One principle ties it together: almost every technical question is really about trade-offs. Faster usually costs more memory, simpler usually costs flexibility, and the strongest answers name the trade-off rather than declaring one option "best." If you are starting from the beginning, KodeKloud's guide to starting with Python is a gentle on-ramp.

Fundamentals

Q1. What is the difference between a compiled and an interpreted language?

A compiled language (C, Go, Rust) is translated ahead of time into machine code by a compiler, producing a binary you run directly, which is fast but platform-specific. An interpreted language (Python, JavaScript) is executed at runtime by an interpreter or virtual machine rather than turned into a standalone binary first, which is more portable and flexible but generally slower. The nuance worth adding: the line is blurry, since languages like Java and C# compile to bytecode that a virtual machine then executes, and Python also compiles to bytecode under the hood. So it is more a spectrum than a binary.

What they're really testing: whether you understand what happens between your source code and the CPU.

Q2. What is the difference between the stack and the heap?

Both are regions of memory, used differently. The stack stores function call frames and local variables, is managed automatically (it grows and shrinks as functions are called and return), and is fast but limited in size. The heap is for dynamically allocated data that must outlive a single function call, is larger, and is managed manually (C) or automatically (CPython uses reference counting plus a cyclic garbage collector; Java uses a tracing garbage collector). The practical tie-in: deep or infinite recursion exhausts the stack and causes a stack overflow (Q17), while leaking heap objects causes memory bloat.

Q3. What is the difference between value types and reference types?

A value type holds its data directly, so assigning or passing it copies the value. A reference type holds a pointer to data elsewhere (usually the heap), so assigning or passing it copies the reference, and both names point at the same underlying object. This is the root of a lot of bugs: mutating an object through one reference changes what every other reference sees. Languages differ in which types are which, and understanding it is what makes the pass-by-value-versus-reference question (Q18) make sense.

Q4. What is the difference between == and is (equality versus identity)?

== checks whether two values are equal; is checks whether two names refer to the same object in memory (identity). Two different lists with identical contents are == but not is. The common gotcha: in CPython, small integers and short strings are cached and reused, so a is b can surprisingly be true for them, which is an implementation detail you should never rely on. The rule: use == to compare values, and reserve is for identity checks like x is None.

Q5. When would you use a list (array) versus a dictionary (hash map)?

Use a list when order matters and you access by position or iterate; use a dictionary when you look things up by a key. The deciding factor is access pattern and cost: indexing a list by position is O(1), but searching it for a value is O(n), while a dictionary lookup by key is O(1) on average. So if you find yourself scanning a list to check membership, that is usually the signal to reach for a dict or set (Q9). Choosing the right one is often the difference between O(n) and O(n squared) code.

Q6. What is Big-O notation?

Big-O describes how an algorithm's time or memory grows as the input grows, ignoring constants and focusing on the dominant term. It is about scaling, not stopwatch seconds. The same function shows why it matters: naive recursive Fibonacci is O(2^n), while adding memoization makes it O(n).

Big O: fib(33)
naive   O(2^n) : 0.6002s
memoized O(n)  : 0.000050s

Same result, the same machine, a difference of more than ten-thousand-fold, purely from complexity. Common classes to know, best to worst: O(1), O(log n), O(n), O(n log n), O(n squared), O(2^n). Being able to state the complexity of your own code is non-negotiable in most interviews.

Q7. What are the four pillars of object-oriented programming?

Encapsulation (bundling data with the methods that operate on it, and hiding internal state), abstraction (exposing a simple interface while hiding complexity), inheritance (a class deriving behavior from a parent), and polymorphism (different types responding to the same interface in their own way). The answer that stands out goes one level deeper: the point of all four is managing complexity and change, letting you swap or extend parts without rewriting everything. Reciting the four words is table stakes; explaining what they buy you is the signal.

Q8. What is the difference between an array and a linked list?

An array stores elements in contiguous memory, so access by index is O(1), but inserting or deleting in the middle is O(n) because elements must shift. A linked list stores each element with a pointer to the next, so inserting or deleting (given the node) is O(1), but accessing the nth element is O(n) because you must walk the chain. The trade-off in one line: arrays favor fast indexed access, linked lists favor fast insertion and deletion. Arrays also have better cache locality, which makes them faster in practice more often than the theory suggests.

Data Structures and Algorithms

Q9. When would you use a hash map, and what is its complexity?

When you need fast lookup, insertion, and deletion by key, all O(1) on average (O(n) worst case under heavy collisions). It is the workhorse of interview problems because it trades memory for speed: store what you have seen so you do not have to search for it again. The difference against a linear scan is not subtle:

membership test for the worst-case element (N=1,000,000)
list  (O(n)) : 20.762 ms
set   (O(1)) : 0.00209 ms

That is the same question ("is this value present?") answered about ten-thousand times faster by the right structure. Whenever a brute-force solution scans a collection repeatedly, a hash map or set is usually how you cut it from O(n squared) to O(n).

Q10. What is the difference between a stack and a queue?

A stack is last-in-first-out (LIFO): the last thing you push is the first you pop, like a stack of plates. A queue is first-in-first-out (FIFO): items leave in the order they arrived, like a line at a counter. Use a stack for things like undo history, expression parsing, or tracking function calls (the call stack itself), and a queue for scheduling, breadth-first traversal, or any "process in arrival order" task. Both are simple, and naming a concrete use for each is what shows you have actually used them.

Q11. What is recursion, and when would you use it over iteration?

Recursion is a function calling itself on a smaller subproblem until it hits a base case that stops the recursion. It shines on naturally recursive structures (trees, nested data, divide-and-conquer algorithms) where it reads far cleaner than loops. The trade-offs to mention: each call adds a frame to the stack, so deep recursion risks a stack overflow (Q17), and naive recursion can repeat work (the O(2^n) Fibonacci in Q6). Iteration uses constant stack space and is often faster, so the choice is clarity versus stack cost. Anything recursive can be rewritten iteratively.

Linear search checks each element in turn, O(n), and works on any collection. Binary search repeatedly halves a sorted range, O(log n), which is dramatically faster but has a hard precondition: the data must be sorted. That precondition is the whole point of the question, because candidates reach for binary search and forget the array has to be sorted first (and sorting it is O(n log n), which may cost more than a single linear scan). Fast, but only when the setup allows it.

Q13. Explain a sorting algorithm and its time complexity.

Take merge sort: it divides the array in half, recursively sorts each half, then merges the two sorted halves, giving a reliable O(n log n) in all cases at the cost of O(n) extra space. Quicksort is the other common answer, also O(n log n) on average but O(n squared) in the worst case (bad pivots), though it sorts in place. The level-up point: most languages' built-in sort is an optimized hybrid (such as Timsort in Python), so in practice you call the library sort and reserve hand-rolled sorting for when an interviewer asks. Know one well enough to explain the mechanism and its complexity.

Q14. What is a binary search tree?

A binary search tree is a tree where each node has up to two children, and for every node, everything in its left subtree is smaller and everything in its right is larger. That ordering makes search, insert, and delete O(log n) when the tree is balanced, because each step halves the remaining nodes. The catch worth raising: if you insert sorted data into a naive BST it degenerates into a linked list and degrades to O(n), which is why balanced variants (AVL, red-black trees) exist. The ordering invariant is the key idea.

Q15. What is the time-space tradeoff?

It is the common situation where you can spend memory to save time, or vice versa. Memoization is the textbook example: caching results so you never recompute them turns the O(2^n) Fibonacci from Q6 into O(n), at the cost of storing the cached values.

fib(33): naive 0.6002s  ->  memoized 0.000050s

The reverse also happens: a streaming algorithm uses constant memory but may need more passes over the data. The senior framing is that "optimization" usually means choosing which resource to spend, and the right choice depends on whether time or memory is your real constraint.

Q16. What is the difference between BFS and DFS?

Both traverse graphs or trees, differing in order. Breadth-first search explores level by level using a queue, which finds the shortest path in an unweighted graph. Depth-first search goes as deep as possible down one branch before backtracking, using a stack (or recursion), which is good for exploring all paths, topological sorting, and cycle detection. The mnemonic: BFS uses a queue and goes wide, DFS uses a stack and goes deep. Picking BFS specifically for shortest-path is the detail interviewers listen for.

Q17. What causes a stack overflow?

Too many nested function calls, so the call stack runs out of its limited space. The usual culprit is recursion without a correct base case (infinite recursion), or recursion too deep for the input (recursing once per element on a million-item list). The fix is either an iterative solution that uses the heap instead of the stack, or, in some languages, tail-call optimization. It connects directly to Q11: recursion is elegant, but every call costs a stack frame, and the stack is not infinite.

Advanced Concepts

Q18. What is the difference between pass by value and pass by reference?

Pass by value gives the function a copy, so changes inside do not affect the caller's variable. Pass by reference gives the function access to the original, so changes do persist. Python is best described as "pass by object reference": you pass a reference to the object, so mutating a mutable object (a list) inside a function is visible outside, but rebinding the name is not. This is the source of one of the most famous gotchas, the mutable default argument:

def add_item(item, bucket=[]):
    bucket.append(item); return bucket

add_item("a")  ->  ['a']
add_item("b")  ->  ['a', 'b']   # 'a' leaked: the default list is created once, not per call

The default list is created once when the function is defined, not on each call, so it accumulates across calls. Knowing why is a strong signal of real understanding.

Q19. What is a closure?

A closure is a function that remembers the variables from the scope in which it was created, even after that scope has finished. In languages with first-class functions (functions you can pass around like any value), a closure lets an inner function keep using an outer function's variables. The practical use: building specialized functions (a "multiplier" factory that returns a function multiplying by a captured number), decorators, and callbacks that carry state without a class. It is the functional-programming counterpart to an object holding state.

Q20. What is the difference between concurrency and parallelism?

Concurrency is dealing with many tasks at once by interleaving them (one core switching between tasks), so they make progress together even if not literally simultaneous. Parallelism is doing many tasks at the same instant on multiple cores. The crisp distinction: concurrency is about structure (handling lots of things), parallelism is about execution (doing lots of things at once). You can have concurrency on a single core. If asked about Python specifically, mention the GIL, which limits CPU-bound threads to one at a time, so true parallelism there needs multiple processes.

Q21. What is a race condition, and how do you prevent it?

A race condition is when the correctness of the program depends on the unpredictable timing of concurrent operations, classically two threads reading and writing shared state at once, so the result depends on who wins the "race". The example everyone gives: two threads each read a balance, add to it, and write back, and one update is lost. You prevent it by protecting shared state with synchronization (locks, mutexes), using atomic operations, or avoiding shared mutable state altogether (immutable data, message passing). Naming "shared mutable state plus concurrency" as the root cause is the strong answer.

Q22. What is immutability, and why does it matter?

An immutable object cannot be changed after creation; to "modify" it you create a new one. It matters because immutable data is inherently safe to share across threads (no race conditions, Q21), easier to reason about (a value cannot change under you), and useful as dictionary keys and in caching. The trade-off is that creating new objects instead of mutating can cost memory and time. Strings are immutable in many languages, which is why building a string in a loop by concatenation is often slow and a join or builder is preferred.

Q23. How should you handle exceptions?

Catch only the specific exceptions you can actually handle, at the level where you can do something meaningful about them, and let the rest propagate. The anti-patterns to call out: catching everything and silently swallowing it (which hides bugs), and using exceptions for normal control flow. Good practice is to fail loudly with context, clean up resources reliably (a finally block or a context manager like Python's with), and never leave a bare except: pass that turns a crash into silent wrong behavior. "Catch what you can handle, log the rest" is the principle.

Q24. What is the difference between an interface and an abstract class?

An interface defines a contract, a set of methods a class must implement, with no implementation itself, and a class can usually implement many. An abstract class can provide some shared implementation alongside methods subclasses must override, but a class typically extends only one. Use an interface to say "this can do X" across unrelated types, and an abstract class to share common code among related types. The modern guidance to add: favor composition over inheritance, because deep inheritance hierarchies get rigid, and interfaces plus composition usually age better.

Practical and Scenario

Q25. Write a function to check whether a string is a palindrome.

The simplest correct approach is to compare the string to its reverse, which is clean and O(n) time (though s[::-1] builds a reversed copy, so it costs O(n) extra space). A more space-efficient approach uses two pointers from each end moving inward, comparing as they go, which is O(n) time and O(1) extra space.

def is_palindrome(s):
    return s == s[::-1]

The discussion the interviewer wants is around edge cases and requirements: do you ignore case, spaces, and punctuation (a "real" palindrome check usually normalizes first)? Stating your assumptions and naming the two-pointer optimization is what turns a one-liner into a good answer.

Q26. How would you find out if an array contains duplicates?

The fast way trades space for time: put the elements into a hash set as you go, and if you ever try to add one already present, you have a duplicate. That is O(n) time and O(n) space. The alternative is sorting first and checking adjacent elements, O(n log n) time but O(1) extra space if you can sort in place. So the answer is a trade-off question, and naming both options (the hash-set speed play and the sort-based space play) is stronger than giving just one.

Q27. Solve the Two Sum problem efficiently.

Given an array and a target, return the indices of the two numbers that add up to the target. The brute force checks every pair, O(n squared). The efficient solution makes one pass with a hash map: for each number, check whether its complement (target minus the number) is already in the map, and if not, store the number.

def two_sum(nums, target):
    seen = {}
    for i, x in enumerate(nums):
        if target - x in seen:
            return (seen[target - x], i)
        seen[x] = i

two_sum([2, 7, 11, 15], 9)  ->  (0, 1)

That is O(n) time and O(n) space. The move that matters is recognizing that a hash map turns the inner search into an O(1) lookup, the same insight as Q9.

Q28. Your code works on small inputs but is too slow on large ones. How do you diagnose and fix it?

Measure first, do not guess. Profile to find the actual hot spot, because the bottleneck is rarely where you assume. The usual culprit is algorithmic: a nested loop that is O(n squared), or a repeated linear search inside a loop. The fix is almost always a better data structure or algorithm, not micro-optimization, for example replacing a repeated list scan with a hash set lookup:

membership for worst-case element (N=1,000,000): list 20.762 ms  ->  set 0.00209 ms

That single structure change is the difference between code that crawls and code that flies on large input. The method, profile then fix the complexity, is what they are scoring.

Q29. How do you debug a problem you cannot reproduce?

Methodically, not by guessing. First make it reproducible: gather the exact inputs, environment, and timing from logs, because an intermittent bug is usually a hidden dependency (a race condition, uninitialized state, time or timezone, or specific data). Add logging around the suspect path, narrow the search space (binary-search the change history with something like git bisect if it is a regression), and form one hypothesis at a time. Explaining your reasoning out loud (rubber-duck debugging) often surfaces the flaw. The signal here is a calm, systematic process rather than randomly changing things and hoping.

Q30. What makes code "clean", and how do you approach a code review?

Clean code is code that is easy to read and change: clear names, small focused functions that do one thing, minimal duplication, and behavior covered by tests. In a review, I start with correctness (does it do the right thing, including edge cases), then readability (will someone understand this in six months), then design (does it fit the existing patterns), and I keep feedback specific and kind, distinguishing "this is a bug" from "this is my preference". The mature note: optimize for the reader, because code is read far more often than it is written, and clever code that no one can maintain is a liability.

Quick-Revision Cheat Sheet

The night before, scan this instead of rereading the guide.

Concept One-line answer Common gotcha
Big-O How cost grows with input size, not seconds Know your own code's complexity
Array vs linked list Array O(1) index; linked list O(1) insert given the node Linked-list random access is O(n)
Hash map O(1) average lookup; trades memory for speed Use it to kill O(n squared) scans
Binary search O(log n) by halving a sorted range Requires the data to be sorted first
Recursion Self-call to a base case; clean for trees Too deep overflows the stack
Concurrency vs parallelism Handling many vs doing many at once Shared mutable state causes races

Conclusion

The thread through these questions is trade-offs and fundamentals. A hash map buys speed with memory, recursion buys clarity with stack space, immutability buys safety with allocation. Interviewers are not checking whether you memorized that quicksort is O(n log n); they are checking whether you can reason about why, and pick the right tool for a constraint. Hold the intuitions (how each structure behaves, what each algorithm costs) and the specific answers follow.

In the last 48 hours, do not try to memorize all thirty. Pick the data structures you are weakest on and implement them once from scratch, then solve a couple of problems out loud to practice explaining while you code. The fluency you want comes from doing, not reading. KodeKloud's Programming learning path and Python Basics course build exactly these foundations, and if you are heading into an AI or ML role, our AI interview guide picks up where the Python here leaves off. This KodeKloud video is a good starting point if you are new to coding:

Ready to Build the Foundations, Not Just Read Them?

Reading about Big-O and hash maps is one thing. Implementing them, measuring the difference, and solving problems under a little pressure are different skills, and they only come from doing the work. KodeKloud's Programming learning path starts from zero and builds real coding fundamentals, and the Python Basics course (Python Institute approved) gives you hands-on practice and a certification path, so these answers become things you have actually done.

Create your free KodeKloud account ->


FAQs

Q1: Which programming language should I use in the interview?

The one you know best, unless the company specifies otherwise. Interviewers care about your problem-solving and fundamentals, not the language. Python and Java are popular for interviews because they let you focus on logic over boilerplate, but a language you are fluent in always beats a trendy one you fumble.

Q2: How important are data structures and algorithms really?

For most technical screens, very. Even if your day job rarely needs to hand-roll a tree, interviews use these problems to test how you reason about complexity and trade-offs. The good news is that a focused set of structures (arrays, hash maps, stacks, queues, trees, graphs) and patterns covers the large majority of questions.

Q3: Do I need to get the optimal solution immediately?

No. Interviewers want to see your process: state a brute-force approach, analyze its complexity, then improve it while talking through the trade-offs. A working solution you can explain and optimize beats a memorized optimal one you cannot reason about. Communicating clearly is part of the score.

Q4: Are these enough on their own?

They cover the conceptual ground, but coding is a doing skill. Solve problems by hand, implement the core data structures yourself, and practice explaining your reasoning aloud. An interviewer can tell within one follow-up whether you understand a concept or memorized its definition.


Sources: How to Start with Python; Learning Python for Beginners; Programming Learning Path; Python Basics Course. Big-O, hash-versus-list, Two Sum, and mutable-default snippets executed locally in Python 3.14.

Nimesha Jinarajadasa Nimesha Jinarajadasa
Nimesha Jianrajadasa is a DevOps & Cloud Consultant, K8s expert, and instructional content strategist-crafting hands-on learning experiences in DevOps, Kubernetes, and platform engineering.

Subscribe to Newsletter

Join me on this exciting journey as we explore the boundless world of web design together.