Skip to content

Graduate Engineer Trainee Interview Questions & Answers

40 questions for Graduate Engineer Trainee interviews — 27 easy, 13 medium.

About the Graduate Engineer Trainee role

Graduate engineer trainees are hired in large batches by IT services and consulting firms through aptitude and coding assessments. Coding sections test basic to medium DSA problems such as arrays, strings, sorting, searching and simple recursion. After training they work on client projects in development, testing or support. Higher-paying digital or specialist tracks within these companies use harder DSA rounds, so strong preparation improves the offer.

Basic DSA Sorting and searching Aptitude Any one language Debugging
Solved for this roleStart practicing
3 QUESTIONS FREESign up to unlock the full question bank and track your progress.Unlock every question and answer, then continue practising company-wise and package-wise.
3 questions free Unlock the rest in seconds
01

Users enter formulas with brackets in a spreadsheet tool. How do you validate that the brackets are balanced?

Save to ▾
Show answer
Scan the formula once with a stack. Push every opening bracket; on a closing bracket, check that the stack is not empty and its top is the matching opening type, then pop. Ignore other characters. At the end the stack must be empty. This is O(n) time and handles nested mixes such as parentheses inside square brackets. To show useful errors, record the position of the first mismatch or unclosed bracket.
02

Check whether a string of brackets is valid.

Save to ▾
Show answer
// Java static boolean isValid(String s) { Deque<Character> st = new ArrayDeque<>(); for (char c : s.toCharArray()) { if (c == '(') st.push(')'); else if (c == '[') st.push(']'); else if (c == '{') st.push('}'); else if (st.isEmpty() || st.pop() != c) return false; } return st.isEmpty(); } // Push the expected closing bracket; O(n) time, O(n) space.
03

Merge two sorted linked lists into one sorted list.

Save to ▾
Show answer
class ListNode: def __init__(self, val=0, nxt=None): self.val = val self.next = nxt def merge(a, b): dummy = tail = ListNode() while a and b: if a.val <= b.val: tail.next, a = a, a.next else: tail.next, b = b, b.next tail = tail.next tail.next = a or b return dummy.next # O(m + n) time, O(1) extra space
04

What is backtracking?

Save to ▾
Show answer
Backtracking builds a solution step by step and abandons a partial solution as soon as it cannot lead to a valid answer, then undoes the last choice and tries the next. It is a DFS over the space of choices. It solves permutations, combinations, subsets, N-Queens, Sudoku and word search. The worst case is often exponential, so good pruning, such as checking constraints early, is what makes it practical.
05

What are a queue, a deque and a circular queue?

Save to ▾
Show answer
A queue is first-in, first-out with enqueue at the back and dequeue at the front, used in BFS, task scheduling and buffering. A deque allows insertion and removal at both ends in O(1), as in Python collections.deque or Java ArrayDeque. A circular queue uses a fixed array with head and tail indices that wrap around modulo capacity, avoiding shifting and wasted space, common in ring buffers and OS schedulers.
06

Check whether a string is a palindrome, ignoring case and non-alphanumeric characters.

Save to ▾
Show answer
// Java static boolean isPalindrome(String s) { int i = 0, j = s.length() - 1; while (i < j) { char a = s.charAt(i), b = s.charAt(j); if (!Character.isLetterOrDigit(a)) { i++; continue; } if (!Character.isLetterOrDigit(b)) { j--; continue; } if (Character.toLowerCase(a) != Character.toLowerCase(b)) return false; i++; j--; } return true; } // Two pointers, O(n) time, O(1) space.
07

Compute the integer square root of a number using binary search.

Save to ▾
Show answer
def int_sqrt(x): lo, hi = 0, x ans = 0 while lo <= hi: mid = (lo + hi) // 2 if mid * mid <= x: ans = mid # mid is a valid candidate lo = mid + 1 else: hi = mid - 1 return ans # int_sqrt(8) -> 2, int_sqrt(16) -> 4; O(log x)
08

Describe a time you got stuck during a coding interview or contest. How did you recover?

Save to ▾
Show answer
Situation: in an online round I could not find an efficient approach for a subarray problem. Task: still score well under time pressure. Action: I first submitted a correct brute-force solution for partial marks, then wrote out small examples and noticed the prefix sums pattern, which led to an O(n) solution with a hash map. Result: I solved it with ten minutes left and learned to secure a working solution before optimising.
09

Your brute-force solution for the longest substring without repeating characters is O(n cubed). How would you improve it?

Save to ▾
Show answer
I would use a variable sliding window. Keep a map from character to its last index and a left pointer. Move the right pointer through the string; when the current character was seen at an index at or after left, move left to that index plus one. Update the best length at each step. Each character is processed a constant number of times, giving O(n) time and O(alphabet size) space.
10

Solve two sum: return the indices of two numbers that add up to the target.

Save to ▾
Show answer
def two_sum(nums, target): seen = {} # value -> index for i, x in enumerate(nums): need = target - x if need in seen: return [seen[need], i] seen[x] = i return [] # two_sum([2, 7, 11, 15], 9) -> [0, 1] # O(n) time, O(n) space; sorting + two pointers gives O(1) space but loses indices
11

How does heap sort work and how does it compare with quicksort and merge sort?

Save to ▾
Show answer
Heap sort builds a max-heap in O(n), then repeatedly swaps the root with the last element, shrinks the heap and sifts down, giving O(n log n) in all cases with O(1) extra space. It is not stable and has poor cache locality, so in practice it is slower than quicksort. Merge sort is stable but needs O(n) space. Introsort switches from quicksort to heap sort to guarantee O(n log n).
12

Tell me about yourself for a software engineer role.

Save to ▾
Show answer
Situation: I am a computer science graduate who enjoys problem solving. Task: become a strong software engineer. Action: I have solved over 400 data structures and algorithms problems, built a campus event app and a file search tool using tries and hashing, and completed an internship where I fixed performance issues in a backend service. Result: I can write clean, efficient code, explain trade-offs clearly, and I am eager to contribute to your engineering team.
13

How does binary search work and what does it require?

Save to ▾
Show answer
Binary search works on sorted data or any monotonic condition. Compare the middle element with the target; if equal, return it, if the target is smaller search the left half, otherwise the right half. Each step halves the search space, giving O(log n) time, so a million elements need about 20 comparisons. It requires random access, so it suits arrays but not linked lists.
14

Implement Kadane's algorithm for the maximum subarray sum.

Save to ▾
Show answer
def max_subarray(nums): best = current = nums[0] for x in nums[1:]: current = max(x, current + x) # extend or start fresh best = max(best, current) return best # max_subarray([-2, 1, -3, 4, -1, 2, 1, -5, 4]) -> 6 (subarray 4, -1, 2, 1)
15

An array of size 100000 must answer 100000 queries asking for the sum between two indices. What approach would you use?

Save to ▾
Show answer
Recomputing each sum is O(n) per query, about 10 to the power 10 operations in total, which is too slow. Since the array does not change, I would build a prefix sum array once in O(n) and answer each query in O(1) as pre[r+1] minus pre[l], giving O(n plus q) overall. If the array also receives updates, I would switch to a Fenwick tree or segment tree for O(log n) updates and queries.
16

Find the next greater element for every element of an array.

Save to ▾
Show answer
def next_greater(nums): res = [-1] * len(nums) stack = [] # indices with decreasing values for i, x in enumerate(nums): while stack and nums[stack[-1]] < x: res[stack.pop()] = x stack.append(i) return res # [4, 5, 2, 25] -> [5, 25, 25, -1] # Each index is pushed and popped once: O(n)
17

Strings are immutable in Java and Python. How does that affect algorithm complexity?

Save to ▾
Show answer
Every modification creates a new string, so building a string by concatenation inside a loop can copy characters repeatedly and become O(n squared). Use StringBuilder in Java or collect parts in a list and call join in Python, which is O(n) overall. Immutability also makes strings safe as hash map keys and lets runtimes cache their hash codes, which is why they are good dictionary keys.
18

Describe a team project where one member was not contributing. What did you do?

Save to ▾
Show answer
Situation: in my final-year project a teammate missed several deadlines. Task: complete the project without conflict. Action: I spoke to him privately and learned he struggled with the graph algorithms part. We swapped tasks so he took the UI, and I paired with him for an hour on the core logic. I also set up a weekly checklist for everyone. Result: we submitted on time and he presented the UI section confidently.
19

Print the level order traversal of a binary tree, one list per level.

Save to ▾
Show answer
from collections import deque def level_order(root): if not root: return [] out, q = [], deque([root]) while q: level = [] for _ in range(len(q)): # process exactly one level node = q.popleft() level.append(node.val) if node.left: q.append(node.left) if node.right: q.append(node.right) out.append(level) return out
20

How would you check whether two strings are anagrams, and what changes if input can contain any Unicode characters?

Save to ▾
Show answer
For lowercase English letters, compare character counts using an array of 26 integers in O(n) time and O(1) space; sorting both strings also works in O(n log n). With arbitrary Unicode, use a hash map of counts instead of a fixed array. I would also clarify whether case and spaces matter and whether to normalise accented characters, since visually identical text can have different code point sequences.
21

A warehouse robot moves only right or down on a grid with some blocked cells. How do you count the number of paths?

Save to ▾
Show answer
Use DP where dp[r][c] is the number of ways to reach cell r, c. A blocked cell has 0 ways; the start has 1; every other cell is dp[r-1][c] plus dp[r][c-1]. Fill row by row in O(rows times columns), and keep a single row array to use O(columns) space. Counts can become huge, so problems often ask for the result modulo 10 to the power 9 plus 7.
22

How would you implement browser back and forward navigation?

Save to ▾
Show answer
Use two stacks plus the current page. Visiting a new page pushes the current page onto the back stack, sets the new page as current and clears the forward stack. Back pushes current onto the forward stack and pops the back stack into current. Forward does the reverse. Each operation is O(1). A doubly linked list with a cursor is an alternative that makes it easy to show the full history.
23

A sorted array has been rotated at an unknown point. How can you still search it in O(log n)?

Save to ▾
Show answer
At every step of binary search, at least one half around mid is sorted. Compare nums[low] with nums[mid]: if the left half is sorted and the target lies within its range, search left, otherwise search right. If the right half is sorted, apply the same check on the right. This keeps O(log n). With duplicates allowed, equal values can hide which half is sorted, and the worst case becomes O(n).
24

How can you implement a queue using two stacks, and what is its complexity?

Save to ▾
Show answer
Use an in-stack for enqueue and an out-stack for dequeue. Enqueue pushes onto the in-stack in O(1). For dequeue, if the out-stack is empty, pop everything from the in-stack and push it onto the out-stack, which reverses the order, then pop from the out-stack. Each element moves at most once between stacks, so dequeue is O(1) amortised even though a single transfer can be O(n).
25

Write recursive Fibonacci and then optimise it with memoisation.

Save to ▾
Show answer
from functools import lru_cache def fib_naive(n): # O(2^n) time if n < 2: return n return fib_naive(n - 1) + fib_naive(n - 2) @lru_cache(maxsize=None) def fib_memo(n): # O(n) time, O(n) space if n < 2: return n return fib_memo(n - 1) + fib_memo(n - 2) def fib_iter(n): # O(n) time, O(1) space a, b = 0, 1 for _ in range(n): a, b = b, a + b return a
26

What is the two pointer technique and when is it used?

Save to ▾
Show answer
Two pointers move through an array or string, often from both ends or at different speeds, to avoid nested loops. On a sorted array you can find a pair with a given sum in O(n) by moving left or right depending on the current sum. It is also used for reversing, removing duplicates in place, merging sorted arrays, palindrome checks and partitioning. It usually needs sorted data or a monotonic condition.
27

What are the ways to represent a graph and when would you use each?

Save to ▾
Show answer
An adjacency list stores, for each vertex, a list of neighbours, using O(V plus E) memory; it is best for sparse graphs such as road or social networks and makes iterating neighbours fast. An adjacency matrix uses a V by V grid, O(V squared) memory, with O(1) edge checks; it suits dense or small graphs and Floyd-Warshall. An edge list is a simple list of pairs, convenient for Kruskal's algorithm.
28

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

Save to ▾
Show answer
An array stores elements contiguously, giving O(1) index access and good cache performance, but inserting or deleting in the middle costs O(n) because elements shift. A linked list stores nodes with pointers to the next node, so insertion and deletion at a known node are O(1), but finding the i-th element takes O(n) and each node has pointer overhead. Arrays suit read-heavy work, lists suit frequent splicing.
29

A satellite image is a grid of land and water cells. How do you count the islands?

Save to ▾
Show answer
Treat each land cell as a vertex connected to its four neighbours that are also land. Scan the grid; when you find unvisited land, increase the island count and run DFS or BFS to mark the whole connected island as visited. Each cell is visited once, so the time is O(rows times columns). Use BFS or an explicit stack for very large grids to avoid recursion limits, or Union-Find if cells arrive over time.
30

A learning platform has courses with prerequisites. How do you find a valid order, and what if none exists?

Save to ▾
Show answer
Model courses as vertices with an edge from each prerequisite to the course that needs it, then run topological sort with Kahn's algorithm. Courses with no pending prerequisites enter a queue first, and taking one reduces the in-degree of dependent courses. If the output has fewer courses than the total, there is a cycle, so no valid order exists, and I would report the courses involved so the content team can fix them.
31

Write an iterative binary search that returns the index of a target or -1.

Save to ▾
Show answer
// Java static int binarySearch(int[] a, int target) { int lo = 0, hi = a.length - 1; while (lo <= hi) { int mid = lo + (hi - lo) / 2; // avoids overflow if (a[mid] == target) return mid; if (a[mid] < target) lo = mid + 1; else hi = mid - 1; } return -1; } // O(log n) time, O(1) space
32

What is a stack and where is it used?

Save to ▾
Show answer
A stack is a last-in, first-out structure with push, pop and peek, each O(1). It can be built on an array or a linked list. Uses include function call management, undo features, expression evaluation and conversion between infix and postfix, bracket matching, browser history and iterative DFS. In Java use ArrayDeque rather than the legacy Stack class; in Python a list with append and pop works well.
33

What is the difference between a subarray, a subsequence and a substring?

Save to ▾
Show answer
A subarray is a contiguous part of an array, and an array of n elements has n times n plus 1 over 2 of them. A substring is the same idea for strings. A subsequence keeps the original order but may skip elements, so there are 2 to the power n of them. This matters for choosing techniques: sliding window and prefix sums suit subarrays, while subsequence problems often need dynamic programming.
34

Solve climbing stairs: how many ways are there to climb n steps taking 1 or 2 steps at a time?

Save to ▾
Show answer
def climb_stairs(n): if n <= 2: return n prev2, prev1 = 1, 2 # ways(1), ways(2) for _ in range(3, n + 1): prev2, prev1 = prev1, prev1 + prev2 return prev1 # ways(n) = ways(n-1) + ways(n-2): a Fibonacci pattern # climb_stairs(5) -> 8; O(n) time, O(1) space
35

Compare singly, doubly and circular linked lists.

Save to ▾
Show answer
A singly linked list node points only to the next node, using less memory but allowing traversal in one direction. A doubly linked list node also points to the previous node, enabling backward traversal and O(1) deletion of a given node, which LRU caches need. A circular list connects the last node back to the first, useful for round-robin scheduling and buffers. Each extra pointer adds memory and update complexity.
36

Why are you looking for a change from your current job?

Save to ▾
Show answer
Situation: in my current role I have learned a lot maintaining internal tools for two years. Task: I want to grow into harder engineering problems. Action: I have been strengthening my data structures, system design and backend skills through projects and by taking ownership of performance work in my team. Result: I am now ready for a role with larger scale and more technical depth, which is why this position appeals to me.
37

Implement merge sort.

Save to ▾
Show answer
def merge_sort(a): if len(a) <= 1: return a mid = len(a) // 2 left = merge_sort(a[:mid]) right = merge_sort(a[mid:]) out, i, j = [], 0, 0 while i < len(left) and j < len(right): if left[i] <= right[j]: # <= keeps the sort stable out.append(left[i]); i += 1 else: out.append(right[j]); j += 1 out.extend(left[i:]) out.extend(right[j:]) return out # O(n log n) time, O(n) extra space
38

A bug appeared somewhere in the last 1000 commits. How would you find the commit that introduced it quickly?

Save to ▾
Show answer
Commits form an ordered sequence where everything after the bad commit fails and everything before passes, which is a monotonic condition, so binary search applies. Test the middle commit; if it fails, search the earlier half, otherwise the later half. About 10 tests find the culprit among 1000 commits. git bisect automates this, and git bisect run can execute a test script at each step.
39

You are building undo and redo for a text editor. Which data structures would you use?

Save to ▾
Show answer
I would use two stacks. Every user action is pushed onto the undo stack as a command object that knows how to reverse itself. Undo pops from the undo stack, reverts the action and pushes it onto the redo stack. Redo pops from the redo stack and re-applies it. Any new action clears the redo stack. For memory limits, cap the undo stack size, for example using a deque that drops the oldest entries.
40

What is a dummy or sentinel node and why is it useful in linked list problems?

Save to ▾
Show answer
A dummy node is an extra node placed before the real head. It removes special cases for operations that may change the head, such as deleting the first element, merging lists or inserting at the start. You build the result after dummy and return dummy.next at the end. This leads to shorter, less error-prone code, which matters a lot when writing linked list solutions under interview pressure.

Frequently asked questions

What does a Graduate Engineer Trainee do?

Graduate engineer trainees are hired in large batches by IT services and consulting firms through aptitude and coding assessments. Coding sections test basic to medium DSA problems such as arrays, strings, sorting, searching and simple recursion. After training they work on client projects in development, testing or support. Higher-paying digital or specialist tracks within these companies use harder DSA rounds, so strong preparation improves the offer.

Which skills are tested in a Graduate Engineer Trainee interview?

Expect questions on Basic DSA, Sorting and searching, Aptitude, Any one language, Debugging. Most rounds also ask you to explain a project and solve one practical problem live.

How do I prepare for a Graduate Engineer Trainee interview?

Revise Arrays, Strings and Hashing, Sorting, Searching and Backtracking, Linked Lists, Stacks and Queues first using the topic sheets, practise the questions on this page aloud, then do one full mock interview to practise timing.