KS5H446 2.3.1 40 min read 10 question quiz 25 exam marks

Algorithms and Big O Complexity

Searching, sorting, traversals, Dijkstra and A star, and Big O analysis with the reasoning behind each complexity class.

Big O and searching

Big O notation

Big O describes how the resources an algorithm requires grow as the input size n grows. It describes the worst case unless stated otherwise, and it discards constants and lower order terms because only the dominant behaviour matters at scale.

ComplexityNameExamplen = 1,000,000
O(1)ConstantArray access by index, hash table lookup1 operation
O(log n)LogarithmicBinary search, balanced BSTabout 20
O(n)LinearLinear search, one pass over a list1,000,000
O(n log n)LinearithmicMerge sort, quicksort average caseabout 20,000,000
O(n2)PolynomialBubble sort, insertion sort, nested loops1,000,000,000,000
O(2n)ExponentialBrute force subset problemsInfeasible
O(n!)FactorialBrute force travelling salesmanUtterly infeasible

Space complexity describes memory growth in the same way. Merge sort is O(n log n) in time but O(n) in space, which is exactly the trade off against bubble sort's O(1) space.

Linear search

Check each element in turn. O(n) worst case. Works on unsorted data, requires no preparation.

Binary search

Requires sorted data. Compare with the middle element and discard half the remaining range each time.

OCR reference language
function binarySearch(list, target)
    low = 0
    high = list.length - 1
    while low <= high
        mid = (low + high) DIV 2
        if list[mid] == target then
            return mid
        elseif list[mid] < target then
            low = mid + 1
        else
            high = mid - 1
        endif
    endwhile
    return -1
endfunction

O(log n), because each comparison halves the search space. On a million items that is about twenty comparisons rather than a million.

Why sorting first can still be worth it

Sorting costs O(n log n), which is more than a single linear search. But if the data will be searched many times, that cost is paid once and every subsequent search drops from O(n) to O(log n).

Binary search halving the list three timesBinary search looking for 12 in the sorted list 2, 5, 8, 12, 16, 23, 38, 56, 72, 91, 100. Step one sets low to the first item and high to the last, giving a midpoint of 23. The target 12 is smaller than 23, so the whole right half including 23 is discarded. Step two searches 2, 5, 8, 12, 16 with a midpoint of 8. The target 12 is bigger than 8, so 8 and everything to its left is discarded. Step three searches 12 and 16 with a midpoint of 12, which is the target, so the search succeeds after three comparisons rather than the four a linear search would need.Binary search for 12 in a sorted list of 11 items2low58121623mid38567291100highmidpoint is 23. 12 is smaller, so throw away 23 and everything right2low58mid1216high2338567291100midpoint is 8. 12 is bigger, so throw away 8 and everything left25812lowmid16high2338567291100midpoint is 12. Found it, after only three comparisons
Binary search only works on a sorted list. Doubling the list length adds just one extra comparison, which is why it scales so well.
Big O: how the work grows as the input growsA chart of the six common growth rates, with the size of the input along the bottom and the amount of work up the side. O of 1 is a flat line: the work does not depend on the size of the input. O of log n rises very slowly. O of n is a straight line: double the input and you double the work. O of n log n is slightly steeper than that. O of n squared curves up sharply and O of 2 to the n shoots off the top of the chart almost at once. A panel on the right gives each one a feel: O of 1 is opening the first page, O of log n is halving a phone book again and again, O of n is reading every page, O of n log n is merge sorting a pile of cards, O of n squared is comparing every pair of people, and O of 2 to the n is trying every combination. Big O counts steps, not seconds, and describes how the work grows, not how long a particular run takes.How the work grows with the inputsize of the input, nwork1What each one feels likeO(1)open the first pageO(log n)halve a phone book,again and againO(n)read every pageO(n log n)merge sort a pile ofcardsO(n²)compare every pairof peopleO(2ⁿ)try every combination2it counts steps, not seconds
  1. Each curve shows how the work grows as the input gets bigger.
  2. From flat, to slow, to straight, to steep, to explosive: O(1), O(log n), O(n), O(n log n), O(n²), O(2ⁿ).
Big O compares algorithms by how they scale. It ignores the speed of any particular machine.
Linear search and binary search, looking for 38Two ways of finding the number 38 in a sorted list of fifteen numbers. In a linear search the program looks at the items one at a time from the left, so it has to look at the first nine and reject each one before it finds 38 on the tenth look. In a binary search the program checks the middle item, which is 30. 38 is bigger, so the whole left half is thrown away. It then checks the middle of what is left, which is 47. 38 is smaller, so the right half is thrown away, leaving three items. The middle of those is 38, found on the third look. Binary search takes 3 looks where linear search took 10, and the gap grows as the list grows, but binary search only works if the list is sorted.Linear search: look at every item in turn381114172126303338424751566012345678910not it, not it, not it ...found it on the 10th look1Binary search: halve the sorted list every time3811141721263033384247515660check the middle: 30. 38 is bigger, so drop the left half3811141721263033384247515660check the middle: 47. 38 is smaller, so drop the right half3811141721263033384247515660check the middle: 38. Found it, on the 3rd look2linear: 10 looksbinary: 3 looksbinary search needs a sorted list3
  1. Linear search looks at every item in turn from the start, so it can be slow.
  2. Binary search checks the middle and throws half the list away each time.
  3. 3 looks against 10. The longer the list, the bigger the gap, but binary search needs the list sorted.
Linear works on any list. Binary is far faster, but only on a sorted one.

Sorting algorithms

Bubble sort, O(n2)

Repeatedly compare adjacent pairs and swap if out of order. After each pass the largest remaining value is in place. With a swap flag it terminates early on sorted data, giving O(n) best case.

Space O(1). Simple, and unusable at scale.

Insertion sort, O(n2)

Build a sorted section at the front, inserting each next item into its correct place. Space O(1). Best case O(n) on nearly sorted data, and it can sort a stream as items arrive.

Merge sort, O(n log n)

Divide and conquer. Split the list until each part holds one item, then repeatedly merge sorted sub lists.

OCR reference language
function mergeSort(list)
    if list.length <= 1 then
        return list
    endif
    mid = list.length DIV 2
    left = mergeSort(list[0 to mid-1])
    right = mergeSort(list[mid to end])
    return merge(left, right)
endfunction

Consistently O(n log n) in every case, which is its great strength. Space O(n), because the sub lists must be stored, and that is its cost.

Quicksort, O(n log n) average

Choose a pivot, partition so smaller values are on the left and larger on the right, then recursively sort each partition. Average O(n log n) with better constants than merge sort, so it is usually faster in practice, and space O(log n) for the recursion stack. Worst case O(n2) when the pivot is consistently the smallest or largest element, which is why practical implementations choose the pivot carefully.

Choosing

SituationAlgorithm
Small or nearly sorted listInsertion sort
Guaranteed performance requiredMerge sort
Best average speed, memory limitedQuicksort
Very limited memoryInsertion or bubble sort
Teaching the conceptBubble sort
Merge sort: the divide phase and the merge phaseMerge sort on the list 38, 27, 43, 3, 9, 82, 10, 1. The divide phase splits the list in half repeatedly: first into 38, 27, 43, 3 and 9, 82, 10, 1; then into 38, 27 and 43, 3 and 9, 82 and 10, 1; then into eight single item lists. A list of one item is already sorted. The merge phase then combines pairs, each time comparing the front items of the two lists and taking the smaller. The pairs become 27, 38 and 3, 43 and 9, 82 and 1, 10. Those merge into 3, 27, 38, 43 and 1, 9, 10, 82. Those merge into the final sorted list 1, 3, 9, 10, 27, 38, 43, 82.DIVIDE: split in half until every list holds one item3827433982101382743398210138274339821013827433982101273834398211032738431910821391027384382MERGE: rebuild in pairs, always taking the smaller front item
Merge sort always takes about n log n comparisons, whatever order the list starts in, but it needs extra memory to hold the part lists.

Sorting algorithm visualiser

Run bubble, insertion, merge and quick sort side by side and count the comparisons. This tool needs JavaScript, so turn it on to use it. Everything you need to answer the exam question is explained in the text above.

Merge sort on eight numbers: divide, then mergeMerge sort drawn as a diamond of numbered cards, read from the top down and then back up. The list of eight numbers, 6 3 8 1 7 2 5 4, is divided in half again and again: first into two groups of four, then four groups of two, then eight single cards. A single card is already sorted. Then the groups are merged back together, working upwards. Each merge compares the front card of the two groups and takes the smaller one every time, so the pairs become 3 6, 1 8, 2 7 and 4 5, then the groups of four become 1 3 6 8 and 2 4 5 7, and finally the whole list is merged into 1 2 3 4 5 6 7 8.63817254638172546381725463817254361827451368245712345678dividemerge1 item is sortedto merge:compare thefront of eachgroup, take thesmaller one123
  1. Divide the list in half, again and again.
  2. Stop when every group is a single item. One item is already sorted.
  3. Merge groups back together, taking the smaller front item each time, until one sorted list is left.
Merge sort divides until the pieces are trivial, then does all its real work while merging.
Quick sort on 6 3 9 1 8 4: pick a pivot, partition, repeat on each part, joinQuick sort on the list 6, 3, 9, 1, 8, 4. Step one, pick a pivot, here the first item, 6. Step two, partition: everything smaller than the pivot goes on its left, 3, 1 and 4, and everything larger goes on its right, 9 and 8. The pivot, 6, is now in its final place. Step three, do the same to each part. In the left part 3 is the pivot, with 1 smaller and 4 larger. In the right part 9 is the pivot, with 8 smaller and nothing larger. Step four, join the parts: 1, 3, 4, 6, 8, 9. There is nothing to merge, because the partitioning did the work. On average it takes n log n steps, but the worst case is n squared, when the pivot is always the smallest or the largest item.1Pick a pivotthe first item2Partitionsmaller left, larger right3Repeat on each partrecursively4Join them upnothing to merge639184pivot314698smallerlargerpivot1346893 is the pivot9 is the pivot134689Average n log n. Worst case n squared, if the pivot is always the smallest or largest.
  1. Choose a pivot. Here it is the first item.
  2. Partition: smaller items to its left, larger to its right. The pivot is now in its final position.
  3. Sort each part the same way, recursively. A part of one item is already sorted.
  4. Join the parts in order. There is no merge step.
Merge sort does the easy split and the hard merge. Quick sort does the hard split, the partition, and the merge is nothing at all.
A stable sort keeps equal items in their original order, an unstable sort may notFour people are entered in the order Ana with a score of 70, Ben with 90, Cat with 70 and Dev with 80, and then sorted by score. A stable sort puts them in the order Ana 70, Cat 70, Dev 80, Ben 90, so Ana, who was before Cat, is still before Cat. An unstable sort may give Cat 70, Ana 70, Dev 80, Ben 90, where the two equal scores have swapped. Stability matters when a list is sorted twice, for example by name and then by score: a stable sort keeps the names in order within each score.Before: in the order they were entered1Anascore 70Benscore 90Catscore 70Devscore 80Stable sort2Ana70Cat70Dev80Ben90Ana is still before Catequal scores keep their orderUnstable sort3Cat70Ana70Dev80Ben90Cat is now before Anaequal scores swapped placesWhy it matters:sort a list by name, then by score. A stable sort keeps the names in orderwithin each score. An unstable one scrambles them.
  1. The starting order. Ana and Cat have the same score.
  2. A stable sort keeps Ana before Cat, as they were.
  3. An unstable sort may swap them.
Merge sort and insertion sort are stable. Quick sort in its usual form is not.
Bubble, insertion, merge and quick sort compared on speed, memory and stabilityA table compares four sorting algorithms. Bubble sort is O of n at best, if it stops when a pass makes no swaps, O of n squared on average and at worst, uses O of 1 extra memory and is stable. Insertion sort has the same times, O of n best, O of n squared average and worst, O of 1 memory, and is stable. Merge sort is O of n log n in every case, uses O of n extra memory, and is stable. Quick sort is O of n log n on average and at best, but O of n squared at worst, uses O of log n memory for its recursion, and is not stable. To choose: insertion sort for data that is nearly sorted, merge sort when guaranteed speed matters, and quick sort for the fastest on average, done in place.The four sorts side by side1BestAverageWorstExtra memoryStableBubbleO(n)O(n²)O(n²)O(1)yesInsertionO(n)O(n²)O(n²)O(1)yesMergeO(n log n)O(n log n)O(n log n)O(n)yesQuickO(n log n)O(n log n)O(n²)O(log n)nogoodfairpoorWhich one to choose2Nearly sortedinsertion sort: close to O(n)Guaranteed speedmerge sort: always O(n log n)Fastest on averagequick sort, in place
  1. Compare the sorts on best, average and worst case time, on extra memory, and on whether they are stable.
  2. Choose by the situation: nearly sorted, guaranteed speed, or fastest on average.
Quote the case when you give a complexity. Quick sort is O(n log n) on average but O(n²) at worst.

Graph and tree algorithms

Traversals

Depth first search goes as deep as possible before backtracking, using a stack or recursion. Suits maze solving, topological sorting and finding any path.

Breadth first search explores all neighbours at the current depth before going deeper, using a queue. Finds the shortest path in an unweighted graph, and suits finding the nearest node.

Tree traversals: pre order visits node, left, right and is used for copying a tree. In order visits left, node, right and outputs a binary search tree in ascending order. Post order visits left, right, node and is used for deletion and postfix expressions.

Dijkstra's shortest path

Finds the shortest path from one source to all other nodes in a weighted graph with non negative weights.

  1. Set the source distance to 0 and every other to infinity, and mark all nodes unvisited.
  2. From the unvisited nodes, select the one with the smallest known distance, the current node.
  3. For each unvisited neighbour, calculate the distance through the current node. If it is smaller than the recorded distance, replace it and record the current node as its predecessor.
  4. Mark the current node visited.
  5. Repeat from step 2 until the destination is visited or no reachable unvisited node remains.

The predecessor records allow the actual path to be reconstructed by working backwards from the destination.

Complexity O(n2) with a simple implementation, improving to O(E + V log V) with a priority queue.

Dijkstra cannot handle negative weights

Once a node is marked visited its distance is assumed final, and a negative edge could later produce a shorter route, invalidating that assumption.

A star

An extension of Dijkstra using a heuristic to guide the search towards the goal.

At each step it selects the node with the lowest value of:

f(n) = g(n) + h(n)

where g(n) is the actual cost from the start to n, and h(n) is a heuristic estimate of the cost from n to the goal, commonly the straight line distance.

Because it prefers nodes that appear to lead towards the goal, A star explores far fewer nodes than Dijkstra and reaches the answer much faster. It is guaranteed to find the optimal path provided the heuristic is admissible, meaning it never overestimates the true remaining cost.

Dijkstra is A star with h(n) set to zero for every node.

Dijkstra's algorithm finding the shortest path from A to FA weighted graph of six nodes, A to F, with the weight of each edge written on it, and the shortest path from A to F picked out in coral. Dijkstra's algorithm starts at A with a distance of 0 and every other node at infinity. It repeatedly visits the unvisited node that is nearest to the start and updates its neighbours if the route through it is shorter. It visits A, then C at distance 2, then B at 3, then D at 8, then E at 10 and finally F at 13. The working table records each node's distance and the node it was reached via, and reading the via column back from F gives the path: F from E, E from D, D from B, B from C and C from A. So the shortest path is A, C, B, D, E, F with a total weight of 2 plus 1 plus 5 plus 2 plus 3, which is 13. The direct looking route through the heavy edge from C to E would cost 15.Shortest path from A to F4215810263ABCDEFstartfinishshortest: A, C, B, D, E, F = 2 + 1 + 5 + 2 + 3 = 1312The workingnodedistanceviaA0-C2AB3CD8BE10DF13Evisited in this order:A, C, B, D, E, Falways visit the unvisitednode nearest to the start34
  1. A weighted graph: each edge has a cost, such as a distance or a time.
  2. The shortest route is not always the one with the fewest edges: here it takes five edges to save two units.
  3. The working table holds each node's best distance so far and the node it came via.
  4. Always visit the unvisited node nearest the start, then update its neighbours. Read the route back through the via column.
Dijkstra gives the cheapest route to every node. Show the table, not just the answer.
Breadth first and depth first traversal of the same treeThe same tree of nine nodes, A to I, traversed two ways, with each node numbered in the order it is visited. Breadth first visits level by level: A, then its children B, C and D, then their children E, F, G, H and I. It uses a queue, first in first out, so the nodes found earliest are explored earliest. Depth first goes as deep as it can before backing up: A, then B, then E, back to B and on to F, back up to A and down to C, then G, then D, then H and I. It uses a stack, last in first out, or recursion, which uses the call stack. Both visit every node exactly once, but in a different order.Breadth firstA1B2C3D4E5F6G7H8I9Depth firstA1B2C5D7E3F4G6H8I9visits level by leveluses a queue: first in, first outABCDoutgoes as deep as it can firstuses a stack: last in, first outABE12
  1. Breadth first: visit everything one step away, then everything two steps away, and so on. It uses a queue.
  2. Depth first: follow one branch as far as it goes, then back up and try the next. It uses a stack, or recursion.
Same graph, same nodes. Only the order differs, and the order comes from queue against stack.
Dijkstra and A* finding a path round a wall, and how many cells each one looks atTwo searches find a path from S on the left to G on the right round a wall. Dijkstra's algorithm picks the cell with the smallest distance from the start, so it spreads out in every direction and looks at a large area of the grid. A star picks the cell with the smallest distance travelled plus a heuristic guess of the distance left, so it favours cells that look closer to the goal and looks at far fewer cells. Both find a shortest path of the same length, drawn in red. The explored cells are shaded blue for Dijkstra and green for A star.Dijkstra: looks everywhere1SGlooked at 98 cells, path of 15 stepsA*: looks towards the goal2SGlooked at 38 cells, path of 15 stepsThe only difference is a guess3Dijkstra picks the cell with the smallest distance from the start: g.A* picks the smallest g + h, where h is a guess of the distance left, so it favours cells that look closer to the goal.
  1. Dijkstra explores in every direction, cell by cell in order of distance from the start.
  2. A* adds a heuristic, a guess of the distance still to go, so it heads for the goal.
  3. The difference is one guess: g for Dijkstra, g plus h for A*. The heuristic must never overestimate.
A* finds the same shortest path as Dijkstra, but looks at far fewer cells, as long as the heuristic never overestimates.

Key terms you must be able to define

Big O notation
A description of how an algorithm's resource use grows with input size, in the worst case.
Time complexity
How the number of operations grows as the input size increases.
Space complexity
How the memory required grows as the input size increases.
Linear search
Checking each element in turn, O(n), requiring no ordering.
Binary search
Halving a sorted range at each comparison, O(log n).
Merge sort
A divide and conquer sort with consistent O(n log n) time and O(n) space.
Quicksort
A partitioning sort averaging O(n log n) with O(n squared) worst case.
Pivot
The element around which quicksort partitions the data.
Depth first search
A traversal exploring as deep as possible before backtracking, using a stack.
Breadth first search
A traversal exploring all nodes at one depth before going deeper, using a queue.
Dijkstra's algorithm
An algorithm finding the shortest path in a weighted graph with non negative weights.
A star
A pathfinding algorithm using a heuristic estimate to guide the search towards the goal.
Admissible heuristic
A heuristic that never overestimates the remaining cost, guaranteeing an optimal result.

Flashcards

Say the definition out loud before you flip the card. Retrieving it from memory is what builds recall, reading it again is not.

DefineBig O notation
AnswerA description of how an algorithm's resource use grows with input size, in the worst case.
DefineTime complexity
AnswerHow the number of operations grows as the input size increases.
DefineSpace complexity
AnswerHow the memory required grows as the input size increases.
DefineLinear search
AnswerChecking each element in turn, O(n), requiring no ordering.
DefineBinary search
AnswerHalving a sorted range at each comparison, O(log n).
DefineMerge sort
AnswerA divide and conquer sort with consistent O(n log n) time and O(n) space.
DefineQuicksort
AnswerA partitioning sort averaging O(n log n) with O(n squared) worst case.
DefinePivot
AnswerThe element around which quicksort partitions the data.

Reach the top grade on this topic

  • State a complexity and justify it, for example that binary search is O(log n) because each comparison halves the range
  • Give the space complexity as well as the time complexity when comparing sorts
  • Know that DFS uses a stack and BFS uses a queue, and what each is therefore good at
  • Trace Dijkstra with a full table of distances, predecessors and visited nodes
  • Explain A star's f = g + h and why an admissible heuristic guarantees optimality
  • Justify a choice of algorithm against the properties of the data in the question

Mistakes that cost marks here

Avoid these
  • Quoting a complexity with no justification for why it is that class.
  • Comparing sorts on time only, ignoring merge sort's O(n) space cost.
  • Applying binary search to unsorted data.
  • Using Dijkstra on a graph with negative weights.
  • Saying A star is always faster with no mention of the heuristic having to be admissible.
  • Confusing depth first and breadth first, and which structure each uses.
Fun fact

Dijkstra devised his shortest path algorithm in about twenty minutes in 1956 while sitting in a cafe with his fiancee, without pencil or paper. He said the absence of paper forced him to avoid all avoidable complexity.

Knowledge check

0 of 10 answered
1What is the time complexity of binary search?
2Which sorting algorithm has consistent O(n log n) performance in all cases?
3What is the space complexity of merge sort?
4Which data structure does breadth first search use?
5Why can Dijkstra's algorithm not handle negative edge weights?
6In A star, what does f(n) = g(n) + h(n) represent?
7What makes a heuristic admissible?
8Which traversal of a binary search tree produces sorted output?
9Why is bubble sort O(n squared)?
10An algorithm takes 1 second on 1000 items and 100 seconds on 10000 items. What is its likely complexity?
Score 0 / 10

Exam-style questions

Five written questions in the style of the real paper. Write a full answer, then let the marker check it against the mark scheme.

25 marks
1Explain what Big O notation describes and why constants are ignored.3 marks
Explain

Mark scheme0 / 3
  • LIt describes how resource use grows as the input size increases
  • LIt describes the worst case unless otherwise stated
  • LConstants and lower order terms are ignored because only dominant growth matters at scale
Model answer

Big O notation describes how the resources an algorithm requires, usually time but also memory, grow as the size of the input increases, and unless stated otherwise it describes the worst case, giving an upper bound on the behaviour. Constants and lower order terms are discarded because they become insignificant as the input grows. An algorithm taking 3n squared plus 100n plus 5000 operations is written as O(n squared), because once n is large the squared term dominates completely and the difference between 3n squared and n squared is a fixed multiple that does not change the fundamental scaling behaviour. This matters because the purpose of Big O is to compare how algorithms behave as data grows, not to predict exact runtimes on a particular machine.

The marker looks for key phrases. If you said it another way and it is still right, give yourself the mark.
2Compare merge sort and quicksort in terms of time complexity and space complexity.5 marks
Compare

Mark scheme0 / 5
  • LMerge sort is O(n log n) in all cases including the worst
  • LQuicksort averages O(n log n) but degrades to O(n squared) in the worst case
  • LThe quicksort worst case occurs when the pivot is consistently the smallest or largest element
  • LMerge sort requires O(n) additional space for the sub lists
  • LQuicksort sorts largely in place using only O(log n) stack space
Model answer

Merge sort has time complexity O(n log n) in the best, average and worst cases alike, because it always divides the list exactly in half regardless of the data and always performs the same merging work. Quicksort has average time complexity O(n log n) and in practice usually outperforms merge sort because its constant factors are smaller, but its worst case is O(n squared). That worst case occurs when the chosen pivot is consistently the smallest or largest remaining element, so each partition removes only one item rather than roughly half, and it arises naturally if the first element is chosen as the pivot on data that is already sorted. Practical implementations avoid it by choosing the pivot as the median of three candidates or at random. Space is where the comparison reverses. Merge sort requires O(n) additional memory because the sub lists produced by the divide phase must be stored while merging, whereas quicksort partitions the array in place and needs only O(log n) stack space for its recursive calls. The choice therefore depends on priorities: merge sort when guaranteed performance is essential or when sorting data that does not fit in memory, quicksort when average speed matters most and memory is constrained.

The marker looks for key phrases. If you said it another way and it is still right, give yourself the mark.
3Describe how Dijkstra's algorithm finds the shortest path between two nodes in a weighted graph.6 marks
Describe

Mark scheme0 / 6
  • LThe source node distance is set to zero and all others to infinity
  • LThe unvisited node with the smallest known distance is selected as the current node
  • LFor each unvisited neighbour the distance through the current node is calculated
  • LIf that distance is smaller than the recorded distance it replaces it
  • LThe predecessor is recorded so the path can be reconstructed
  • LThe current node is marked visited and the process repeats until the destination is reached
Model answer

Dijkstra's algorithm begins by setting the distance to the source node as zero and the distance to every other node as infinity, with all nodes marked unvisited. It then repeatedly selects, from among the unvisited nodes, the one with the smallest recorded distance, and treats this as the current node. For each unvisited neighbour of the current node, it calculates the distance to that neighbour by travelling through the current node, which is the current node's distance plus the weight of the connecting edge. If this calculated distance is less than the distance already recorded for that neighbour, the recorded distance is replaced with the new smaller value and the current node is stored as that neighbour's predecessor. Once all neighbours have been considered, the current node is marked as visited and will not be examined again, because its distance is now known to be final. The process repeats, always choosing the unvisited node with the smallest distance, until the destination has been visited or no reachable unvisited node remains. The shortest path itself is then recovered by starting at the destination and following the chain of recorded predecessors back to the source, which yields the route in reverse.

The marker looks for key phrases. If you said it another way and it is still right, give yourself the mark.
4Explain how the A star algorithm differs from Dijkstra's algorithm and why it is usually faster.5 marks
Explain

Mark scheme0 / 5
  • LA star adds a heuristic estimate of the remaining cost to the goal
  • LNodes are selected by the lowest value of f equals g plus h
  • LDijkstra explores outwards in all directions equally
  • LA star prioritises nodes appearing to lead towards the goal, so it examines fewer nodes
  • LIt still finds the optimal path provided the heuristic never overestimates
Model answer

Dijkstra's algorithm always expands the unvisited node with the smallest distance from the source, which means it explores outwards from the start in every direction equally, discovering shortest paths to nodes that lie entirely away from the destination before it happens to reach the destination itself. A star modifies the selection rule by adding a heuristic estimate of the remaining cost from each node to the goal, so it chooses the node with the lowest value of f, where f equals g plus h, g being the actual cost accumulated from the start and h being the estimated cost still to travel. Because a node lying in the direction of the goal receives a low h value, it is selected in preference to a node that is equally close to the start but heading away, so the search is directed rather than uniform and typically examines a small fraction of the nodes that Dijkstra would. Crucially, A star still guarantees the optimal path provided the heuristic is admissible, meaning it never overestimates the true remaining cost, since underestimating simply means the algorithm may explore a few extra nodes rather than committing to a suboptimal route. Straight line distance is the standard admissible heuristic for geographic pathfinding, since no actual route can be shorter than a straight line. Dijkstra can be seen as the special case of A star where h is zero everywhere.

The marker looks for key phrases. If you said it another way and it is still right, give yourself the mark.
5A system stores 10 million records and must be searched frequently by a unique key. Compare linear search, binary search and a hash table for this purpose.6 marks
Compare

Mark scheme0 / 6
  • LLinear search is O(n) and would examine up to 10 million records per search
  • LLinear search requires no ordering but is far too slow at this scale
  • LBinary search is O(log n), needing about 24 comparisons
  • LBinary search requires the data to be kept sorted, which costs time on insertion
  • LA hash table gives average O(1) lookup by calculating the position from the key
  • LRecommends the hash table, noting it does not support ordered or range queries
Model answer

Linear search has time complexity O(n), so on 10 million records it would examine on average five million and at worst all ten million entries for every single query. It has the advantage of requiring no ordering or preparation at all, but at this scale and with frequent searching it is completely impractical. Binary search has complexity O(log n), which reduces the work to about 24 comparisons for ten million records, an improvement of roughly six orders of magnitude. Its precondition is that the data must be kept in sorted order, which means either sorting once at O(n log n) if the data is static, or paying an insertion cost to maintain the ordering as records are added, and inserting into a sorted array requires shifting subsequent elements. A hash table offers average O(1) lookup, because the hash function calculates the storage index directly from the key so no searching of any kind is performed, and the time taken does not increase as the number of records grows. Given that the search is by a unique key and is performed frequently, the hash table is the strongest choice, and it should be sized so the load factor stays low enough that collisions remain rare. The one caveat is that a hash table imposes no useful ordering on the data, so if the system also needs to retrieve records in key order or answer range queries such as all keys between two values, a balanced binary search tree giving O(log n) for both lookup and ordered traversal would be the better overall structure.

The marker looks for key phrases. If you said it another way and it is still right, give yourself the mark.
Machine mark 0 / 25