Software Engineering is 4-6 questions on the FE Electrical exam. It tests reading rather than writing code: the complexity of an algorithm, the cost of an operation on a data structure, and the output of a short piece of pseudocode.
Candidates who have not programmed recently should practise tracing loops by hand with a table of variable values, because that is the format of most implementation questions.
Exam weight: NCEES lists Software Engineering at 4-6 questions (4-5%) of the 110-question FE Electrical and Computer exam. Work each problem below on paper first, then reveal the worked solution — reading a solution you have not attempted builds recognition, not recall.
What NCEES Tests in Software Engineering
The specification lists algorithms (sorting, searching, complexity, big-O), data structures (lists, trees, vectors, structures, arrays) and software implementation (iteration, conditionals, recursion, control flow, scripting, testing).
The specification lists algorithms (sorting, searching, complexity, Big-O), data structures (lists, trees, vectors, structures, arrays) and software implementation (iteration, conditionals, recursion, control flow, scripting, testing).
Expect the Big-O class of a nested loop, the number of comparisons of a binary search, the complexity of the common sorts, the right structure for a stated access pattern, the traversal order of a tree, the output of a pseudocode fragment, the base case of a recursion, and the level or kind of a test.
5 Free Software Engineering Practice Problems
Each problem below comes from the PECivilClick FE Electrical question bank, with a worked solution that cites its FE Reference Handbook page, and matches the style, difficulty and format of the real exam. Attempt each one under a three-minute limit — roughly the pace the exam demands.
Problem 1 — A. Algorithms (sorting, searching, complexity, big-O)
What is the worst-case time complexity of a linear search through an unsorted array of \(n\) elements?
Answer: C) \(O(n)\)
A linear search compares the target with one element after another, in order, until it finds a match or runs off the end. Nothing about an unsorted array lets it skip anything: in the worst case the target is the last element, or is absent altogether, and every one of the \(n\) elements has been examined.
$$T(n) = n \text{ comparisons} = O(n)$$
Big O describes how the work grows with \(n\), and here it grows in direct proportion: double the array, double the worst-case work. Linear search is not in the Handbook's efficiency table, but it is the baseline every entry in that table is measured against.
\(O(\log n)\) is binary search, which halves the remaining range at each comparison. It needs the array to be sorted; on an unsorted array there is no way to know which half to discard.
\(O(1)\) is constant time, the cost of a hash-table lookup or of reading one array element by index. A search that must look at the data cannot run in time independent of how much data there is.
\(O(n \log n)\) is the cost of a good sort, not of a search. Sorting first and then binary-searching would cost more than one linear pass, not less.
Problem 2 — B. Data structures (lists, trees, vectors, structures, arrays)
What is the time complexity of reading the element at index \(i\) of an array of \(n\) elements?
Answer: A) \(O(1)\)
The Handbook defines an array as a collection whose elements are accessed by an integer index, and that definition hides the reason for the answer. An array's elements sit in consecutive memory locations, so the location of element \(i\) is a single arithmetic expression:
$$\text{address of element } i = \text{start of array} + (i - 1) \times \text{size of one element}$$
One multiplication and one addition, whatever the value of \(i\) and whatever the size of the array. That is constant time, \(O(1)\), and it is the single property that makes arrays the right structure whenever data is read by position - it is also what binary search relies on to jump to the middle.
\(O(i)\) is the cost of reaching position \(i\) in a linked list, whose nodes can only be found by following pointers from the head one node at a time. It is the natural wrong answer for anyone picturing the wrong structure.
\(O(n)\) is the cost of searching an unsorted array for a value. Reading by index and searching by value are different operations; only the second has to look at the data.
\(O(\log n)\) is binary search, again a search by value and one that needs sorted data.
Problem 3 — C. Software implementation (iteration, conditionals, recursion, control flow, scripting, testing)
What value does the call factorial(5) return?
function factorial(n: integer)
if n <= 1 then
return 1
else
return n * factorial(n - 1)
end if
end function
Answer: C) 120
A recursive function is read by unwinding it. Each call with \(n > 1\) multiplies \(n\) by the result of the call for \(n - 1\), and the chain stops at the base case \(n \le 1\), which returns 1 without calling anything:
$$\text{factorial}(5) = 5 \cdot \text{factorial}(4) = 5 \cdot 4 \cdot \text{factorial}(3) = 5 \cdot 4 \cdot 3 \cdot 2 \cdot \text{factorial}(1) = 5 \cdot 4 \cdot 3 \cdot 2 \cdot 1 = 120$$
The base case is what makes the recursion finish: without it the calls would descend through 0, \(-1\), \(-2\) and never return. The Handbook does not describe recursion, so the discipline of checking for the base case first is one to bring to the exam.
24 is \(4!\), the result of stopping one level early - reading the base case as \(n \le 2\), or forgetting the outermost factor of 5.
720 is \(6!\), one level too many.
60 is \(5 \cdot 4 \cdot 3\), the chain abandoned before reaching the base case.
Problem 4 — A. Algorithms (sorting, searching, complexity, big-O)
An algorithm runs in \(O(n^2)\) time. If the input size doubles, by roughly what factor does its running time increase?
Answer: B) 4
Quadratic time means the running time is proportional to the square of the input size. Doubling the input squares the doubling:
$$\dfrac{T(2n)}{T(n)} = \dfrac{c(2n)^2}{cn^2} = \dfrac{4cn^2}{cn^2} = 4$$
The constant \(c\) cancels, and so does \(n\): for any polynomial the ratio is the same whatever the starting size, which is exactly why Big O is useful. It tells you how an algorithm scales without knowing how fast the machine is. The rule generalises: an \(O(n^k)\) algorithm slows by \(2^k\) when the input doubles, so the exponent is the whole story.
2 is the linear answer, \(O(n)\): doubling the input doubles the work. A quadratic algorithm does worse than that because every element interacts with every other.
8 is \(2^3\), the factor for a cubic algorithm.
16 is \(2^4\), or equivalently the factor of 4 squared a second time - the doubling applied to the exponent as well as to the input.
Problem 5 — A. Algorithms (sorting, searching, complexity, big-O)
What is the time complexity of the following pseudocode as a function of \(n\)?
for i = 1 to n
j = 1
while j <= n
sum = sum + 1
j = j * 2
end while
end for
Answer: C) \(O(n \log n)\)
Count the inner statement's executions. The outer loop runs \(n\) times. Inside it, \(j\) starts at 1 and doubles on every pass, so it takes the values \(1, 2, 4, \ldots, 2^k\) and the loop continues while \(2^k \le n\) - that is, \(\lfloor \log_2 n \rfloor + 1\) passes. The inner count does not depend on \(i\), so the total is simply the product:
$$n \times (\lfloor \log_2 n \rfloor + 1) = O(n \log n)$$
The rule to carry away: a loop whose variable is multiplied by a constant each time runs a logarithmic number of times, while one whose variable is incremented runs a linear number of times. Nested loops multiply their counts.
\(O(n^2)\) treats the inner loop as linear, as it would be if \(j\) advanced by \(j = j + 1\). The doubling is what changes everything.
\(O(n)\) counts only the outer loop, as though the inner one ran a constant number of times. It runs \(\log_2 n\) times, and that grows.
\(O(\log^2 n)\) makes both loops logarithmic. The outer variable is incremented, not doubled, so it is linear.
Using the FE Reference Handbook for Software Engineering
The Handbook's software material is on pp. 411-413: pointers, hashing and the sorting algorithms on p. 411, data structures including stacks, queues, linked lists and trees on p. 412, and pseudocode conventions with the algorithm-efficiency (Big-O) discussion and binary search on p. 413. Testing levels and development processes are not in the body; they appear in the exam specification and are tested from definitions.
Four Mistakes That Cost Points
- Reporting the average case when the question asks for the worst. Quicksort is n log n on average but n squared in the worst case; a hash lookup is constant on average but linear in the worst case. Big-O questions usually mean the worst case unless they say otherwise.
- Miscounting loop iterations at the boundaries. A loop from one to n inclusive runs n times; a loop from zero to n minus one also runs n times; a loop from one to n exclusive runs n minus one. Off-by-one errors are the most common wrong answer in pseudocode questions.
- Choosing a linked list for index access. A linked list gives constant-time insertion at a known node but linear-time access by position. An array or vector gives constant-time index access. The question tells you which operation dominates.
- Forgetting that a binary search needs sorted data. The logarithmic cost assumes the array is sorted. On unsorted data the search is linear, or you must add the cost of sorting first.
Frequently Asked Questions
How many software engineering questions are on the FE Electrical exam?
NCEES specifies 4-6 questions out of 110, about 4 to 5 percent of the exam.
Which sorting complexities should I know?
Bubble, selection and insertion sort are n squared; merge sort and heap sort are n log n in every case; quicksort is n log n on average and n squared in the worst case. Comparison sorting cannot beat n log n.
What pseudocode conventions does the exam use?
The conventions on p. 413 of the Handbook: indentation for blocks, a left arrow for assignment, and for, while and if constructs. Questions ask for the value of a variable after the code runs.
Is any particular programming language required?
No. Questions are language-neutral pseudocode or general concepts such as pass by value versus reference, scope, recursion and testing levels.
Keep Going
These topics feed into each other on the exam:
- FE Electrical Computer Systems practice problems — 5-8 questions on the exam
- FE Electrical Digital Systems practice problems — 8-12 questions on the exam
- FE Electrical Mathematics practice problems — 11-17 questions on the exam
Done with software engineering? Browse every knowledge area from the free FE Electrical practice problem hub, see what the full bank covers on the FE Electrical exam prep page, or plan your schedule with the FE study timeline.