Hi friends
I am analyzing the time complexity of this example in the beginning of Chapter 11, Searching (page 147 in the Python book). The search portion is clearly O(log n), but wouldn’t the whole program have a longer runtime since we create a whole new array (O(n)) on which to operate before running the search? (O(n) since O(n) > O(log n).) From the book (please excuse lack of indentation):
Suppose we are given as input an array of students, sorted by descending GPA, with ties broken on name. In the program below, we show how to use the library binary search routine to perform fast searches in this array. In particular, we pass binary search a custom comparator which compares students on GPA (higher GPA comes first), with ties broken on name.
Student = collections.namedtuple(’Student’, (’name’, ’grade_point_average’))
def comp_gpa(student: Student):
return (-student.grade_point_average, student.name)
def search_student(students: List[Student], target: Student, comp_gpa: Callable[[Student], Tuple[float, str]]):
i = bisect.bisect_left([comp_gpa(s) for s in students], comp_gpa(target))
return 0 <= i < len(students) and students[i] == target
Assuming the i-th element in the sequence can be accessed in O(1) time, the time complexity of the program is O(log n).
Can someone help me understand why the solution is considered O(log n) if this is correct? Is there a property of Python lists which lets the remapping occur on access instead of on the entire input list? Love to hear your insight. Thank you!