KarmSakha
Help

Interview & Soft Skills

Coding Interview Questions: 3 Worked Python Answers

These three original coding interview questions practise different skills: preserving order while summarising data, comparing sorted inputs, and tracking nested structure. Each has an explicit contract, a Python answer and examples you can check. They are practice questions written for this guide, not a claim about questions asked by TCS, Infosys or another employer.

Before coding, explain the permitted inputs, required output and cases that could change your approach. The solutions below use strict input checks so the contract is visible. In an actual assessment, follow the supplied language and input requirements rather than assuming this guide's format applies.

Question 1: summarise consecutive repeated readings

Task: Given a Python list of integers, return a list of pairs describing each consecutive run: the value and its count. Preserve run order. Repeated values separated by another value must remain separate runs.

The input must be an exact built-in list containing exact built-in integers. Booleans, integer subclasses, strings and other containers are rejected with TypeError. An empty list returns an empty list. Negative integers are permitted. The function must not change its input.

For [4, 4, -1, -1, -1, 4], the answer is [(4, 2), (-1, 3), (4, 1)]. The last four is a new run; it does not increase the first run to three.

First define the validation helper. Reuse it in the second answer too.

def _ints(xs):
  if type(xs) is not list:
    raise TypeError
  for x in xs:
    if type(x) is not int:
      raise TypeError

Then track the current value and count. When the value changes, emit the completed run. Emit the final run after the loop.

def runs(xs):
  _ints(xs)
  if not xs:
    return []
  out = []
  v = xs[0]
  count = 1
  for x in xs[1:]:
    if x == v:
      count += 1
    else:
      pair = (v, count)
      out.append(pair)
      v = x
      count = 1
  pair = (v, count)
  out.append(pair)
  return out

The useful invariant is that v and count describe the unfinished run, while out contains all completed runs. In the example, the second four makes the count two. Encountering minus one emits (4, 2). The later four emits (-1, 3), and the final append emits (4, 1).

Check [] → [], [7] → [(7, 1)], and [2, 1, 2] → [(2, 1), (1, 1), (2, 1)]. A frequency table would give different information for the last case because it loses run boundaries.

Under the usual interview model that treats integer comparisons as constant-cost, validation and traversal take O(n) time. The output can contain n pairs. This particular implementation also creates a slice with xs[1:], so it uses O(n) temporary storage beyond the output. Do not call it constant-space merely because its current-run variables are small. An indexed traversal could avoid that slice if the task required it.

Question 2: find distinct values shared by sorted lists

Task: Given two ascending integer lists, return the distinct values present in both, in ascending order. Duplicates in either input should appear once in the answer.

Both lists use the same exact-list/exact-integer contract as Question 1. They may be empty and contain negative integers. They must be sorted in nondecreasing order; an unsorted valid integer list raises ValueError. The functions must not modify either input.

For [-2, 1, 1, 4, 8] and [1, 1, 3, 4, 4], the answer is [1, 4]. Validate order before doing the comparison.

def _sorted(xs):
  _ints(xs)
  prev = None
  for x in xs:
    if prev is not None:
      if x < prev:
        raise ValueError
    prev = x

Use one position in each input. Advance the smaller value's position. When the values match, emit the value only if it differs from the last emitted value, then advance both positions.

def shared(a, b):
  _sorted(a)
  _sorted(b)
  out = []
  i = j = 0
  while i < len(a):
    if j == len(b):
      break
    if a[i] < b[j]:
      i += 1
    elif a[i] > b[j]:
      j += 1
    else:
      if not out:
        out.append(a[i])
      else:
        last = out[-1]
        if last != a[i]:
          out.append(a[i])
      i += 1
      j += 1
  return out

In the worked example, minus two is smaller than one, so the first position advances. The matching ones emit one once, including when a second pair of ones is encountered. Three is smaller than four, so the second input advances. The matching fours emit four, and later unmatched values produce no additional output.

Check [1, 1] with [1] → [1], [] with [2] → [], and [-3, 0] with [-2, 0] → [0]. Check that [2, 1] raises an order error instead of silently producing an unreliable answer.

The invariant is that values before each current position have already been accounted for or ruled out. Ascending order is what permits discarding a smaller value: it cannot match a later smaller value in the other input.

With the same constant-cost comparison model, validation and traversal take O(n + m) time. Positions use O(1) auxiliary storage; the output uses O(k), where k is the number of distinct shared values. This answer does not create input slices or sort the inputs. A set-based alternative could be simpler, but it would have different storage and ordering considerations.

Question 3: validate nested brackets

Task: Return whether a string containing only (, ), [, ], { and } is correctly paired and nested. An empty string is valid. Every closing bracket must match the most recent unmatched opening bracket.

The input must be an exact built-in string, or the function raises TypeError. Any other character, including spaces and letters, raises ValueError. A string made entirely of allowed brackets can return False for incorrect pairing. Validate every character first, so ")x" raises for the invalid character rather than returning early at the unmatched closing bracket.

def balanced(text):
  kind = type(text)
  if kind is not str:
    raise TypeError
  for c in text:
    if c not in "()[]{}":
      raise ValueError
  pairs = {
    ")": "(",
    "]": "[",
    "}": "{",
  }
  stack = []
  for c in text:
    if c in "([{":
      stack.append(c)
    elif not stack:
      return False
    else:
      top = stack.pop()
      if top != pairs[c]:
        return False
  return not stack

For "([]){}", the first two opening brackets enter the stack. The closing square bracket removes the square bracket, then the closing round bracket removes the round bracket. The curly pair is processed next, leaving an empty stack: True.

For "([)]", the round closing bracket encounters a square opening bracket at the top: False. Counting two openings and two closings would miss this mismatch. For "(()", one unmatched opening remains at the end: also False.

Check "" → True, "()[]" → True, ")(" → False, and "[{}]" → True. Distinguish a permitted-but-unbalanced input from an invalid-character input such as "[a]".

The stack holds the unmatched openings in their arrival order; its top is the one the next closing bracket must match. Validation and processing take O(n) time. In the worst case, n opening brackets remain on the stack, giving O(n) auxiliary storage. This is a small bracket exercise, not a parser for Python or another programming language.

Explain the answer before optimising it

For each question, give a small example, the invariant, the reason a position advances or a state changes, and a boundary case. State which costs your complexity model treats as constant. Python's integers can have varying size, so the simple interview complexity descriptions above are not a bit-level analysis of arbitrarily large values.

If asked to optimise Question 1, discuss removing the temporary slice before claiming improved memory use. If asked to support unsorted inputs in Question 2, clarify whether you may sort copies and whether the result must retain an original order. If asked to ignore ordinary text in Question 3, agree on a new contract and change both validation and tests; do not quietly answer a different problem.

Build a practice record

Attempt a question without reading its answer, then compare your output on the supplied examples. Record any mismatch and the smallest input that exposes it. Run additional tests against an independently constructed expected result rather than merely asserting the output your code already produced.

Separate a proposed test from a test you actually executed. Likewise, passing these exercises establishes a bounded coding result, not readiness for every employer's assessment or a guarantee of an offer. Use the actual recruitment instructions for assessment logistics and permitted resources.

Frequently asked questions

Why reject booleans as integers?

That is the explicit contract of these exercises. Python's type relationships could permit them under a different check, so the strict helper deliberately uses exact type comparisons. Another task may choose a broader numeric contract.

Should I memorise these answers?

Use them to check your reasoning. Try different inputs and explain why the algorithm remains correct. Memorising the syntax does not show that you can adapt to a changed requirement.

Are these actual company interview questions?

No. These are independently written practice exercises. They do not claim employer endorsement, leaked questions or a particular company's test format.

Further reading and related guides

Python's built-in type documentation describes boolean and integer relationships, sequence operations and list methods. The question contracts, examples and implementations here are independently written practice material.

Use the problem-solving skills guide and the technical interview guide for broader preparation. These resources do not establish any employer's actual question list.

Related guides

Ask KarmSakha AI