Question 1[14 marks]
A school library looks up books by their ID numbers.
Complete the trace table for this Python code. A school library keeps its book IDs in ids, sorted from smallest to largest. This code is a binary search for the book with ID 150. // divides and keeps only the whole number part, and found stays -1 until the book is found. Then answer the question below the table. [4]
ids = [104, 117, 123, 138, 150, 162, 171]
target = 150
low = 0
high = len(ids) - 1
found = -1
while low <= high and found == -1:
mid = (low + high) // 2
if ids[mid] == target:
found = mid
elif ids[mid] < target:
low = mid + 1
else:
high = mid - 1
How many positions of ids did the loop look at in all, including the one where it found 150?
The table, made by running the code:
| low | high | mid | found |
|---|---|---|---|
| 0 | |||
| 6 | |||
| -1 | |||
| 3 | |||
| 4 | |||
| 5 | |||
| 4 | |||
| 4 | |||
| 4 |
- p1 [1]
The
midcolumn shows 3, then 5, then 4. - p2 [1]
The
lowcolumn starts at 0 and changes once, to 4, and thehighcolumn starts at 6 and changes once, to 4. - p3 [1]
The
foundcolumn starts at -1 and changes once, to 4, as the last change in the table. - p4 [1]
States 3 positions (3, 5 and 4).
A school library gives every book a whole-number ID. The IDs are kept in a list (an array in Java) called ids, sorted from smallest to largest, with no ID appearing twice.
Write a function that uses a binary search to return the position (the index) of target in ids, or -1 if no book has that ID. Positions start at 0.
- Keep two positions,
lowandhigh, for the part of the list that could still holdtarget. They start at the first and the last position. - Look at the middle position,
(low + high)divided by 2, rounded down. If the ID there istarget, return that position. If it is smaller thantarget, search only the part after it; if it is larger, search only the part before it. - When
lowhas passedhigh, nothing is left to search, so return-1. idscan be empty, and holds at most 10000 IDs, each between 1 and 1000000.- Write the search yourself. The shortcuts listed with this question are not allowed.
The tests check only the number your function returns, so they cannot tell a binary search from a linear one. In the exam, a linear search would not earn the marks for this part.
def find_book(ids: list[int], target: int) -> int
public static int findBook(int[] ids, int target)
A Paper 2 question that asks for a binary search wants to see the search written out, so the built-in searches are not allowed.
Marked by running your code against tests. Open it in the runner to check your answer. The hidden tests check:
- an empty list (rule 4)
- the first ID in the list
- the last ID in the list
- an even number of IDs, so the middle is rounded down (rule 2)
- a missing ID smaller than every ID (rule 3)
- a missing ID larger than every ID (rule 3)
- a longer list, wanted ID at the very end
- one book, not the one wanted
[6]
A school library keeps the IDs of its 1000 books in a list (an array in Java), and a librarian looks up one ID at a time.
(a) Explain why a binary search only works if the IDs are sorted. [2]
(b) State the largest number of IDs a linear search would have to look at to find one ID, and the largest number a binary search would have to look at, for the 1000 books. [2]
[4]
- p1 [1]
(a) Says that a binary search looks at the middle ID and throws away (does not search) one half of what is left.
- p2 [1]
(a) Says that throwing away a half is only safe when the IDs are sorted, because only then are all the IDs in that half known to be smaller (or larger) than the target; in an unsorted list the target could be in the half thrown away.
- p3 [1]
(b) States 1000 for a linear search.
- p4 [1]
(b) States 10 for a binary search.
Also accept
- For p2, an example of an unsorted list where the search goes the wrong way and misses an ID that is there earns the mark.
- For p4, "about log2(1000), which is 10" earns the mark, and so does "10, because 2 to the power 10 is 1024, which is at least 1000".
No marks for
- For (a), "because binary search needs sorted data". This repeats the question without saying why.
- For (a), "because it is faster". Speed does not explain why an unsorted list gives wrong answers.
- For p4, 500. Halving once is not the whole search; the remaining part is halved again on every look.
- For p4, 9 or 9.97. The search must keep looking until one ID is left, which takes 10 looks for 1000 IDs.
A full-marks answer
(a) A binary search looks at the middle ID and, if it is not the target, keeps only one half of the list and never looks at the other half again (p1). That is only safe when the IDs are sorted, because then every ID in the discarded half is known to be on the wrong side of the target. If the list were not sorted, the target could be in the half that was thrown away, so the search would say it is missing when it is not (p2).
(b) A linear search may have to look at all 1000 IDs (p3). A binary search looks at no more than 10, because each look halves what is left and 2 to the power 10 is 1024, which is at least 1000 (p4).