Implementing the bisect Module in Python
The bisect module in Python provides functions for binary searching and inserting elements into sorted lists while maintaining their sorted order. Implementing this module yourself is a great exercise in understanding binary search algorithms and how they can be applied to maintain sorted data structures efficiently. This challenge asks you to recreate the core functionality of bisect_left and bisect_right from the standard library.
Problem Description
Your task is to implement two functions, bisect_left(list, x) and bisect_right(list, x), which mimic the behavior of the bisect_left and bisect_right functions from Python's bisect module. These functions perform binary searches on a sorted list to find the insertion point for a given element x.
bisect_left(list, x): Finds the index at whichxshould be inserted intolistto maintain sorted order, such that all elements before the insertion point are strictly less thanx. Ifxis already present inlist, the insertion point will be before any existing entries ofx.bisect_right(list, x): Finds the index at whichxshould be inserted intolistto maintain sorted order, such that all elements before the insertion point are less than or equal tox. Ifxis already present inlist, the insertion point will be after any existing entries ofx.
You should implement these functions using a binary search algorithm. The functions should handle empty lists correctly.
Examples
Example 1:
Input: list = [1, 3, 4, 6, 8, 9], x = 5
Output: bisect_left(list, x) -> 3
Output: bisect_right(list, x) -> 3
Explanation: 5 should be inserted at index 3 to maintain sorted order. Both functions return the same index in this case.
Example 2:
Input: list = [1, 3, 4, 6, 8, 9], x = 0
Output: bisect_left(list, x) -> 0
Output: bisect_right(list, x) -> 0
Explanation: 0 should be inserted at the beginning of the list.
Example 3:
Input: list = [1, 3, 4, 6, 8, 9], x = 10
Output: bisect_left(list, x) -> 6
Output: bisect_right(list, x) -> 6
Explanation: 10 should be inserted at the end of the list.
Example 4:
Input: list = [1, 2, 2, 2, 3, 4], x = 2
Output: bisect_left(list, x) -> 1
Output: bisect_right(list, x) -> 4
Explanation: bisect_left finds the leftmost insertion point, while bisect_right finds the rightmost.
Example 5:
Input: list = [], x = 5
Output: bisect_left(list, x) -> 0
Output: bisect_right(list, x) -> 0
Explanation: Handles the empty list case correctly.
Constraints
- The input
listwill contain only comparable elements (e.g., numbers, strings). - The input
listwill be sorted in ascending order. - The input
xwill be a comparable element. - The length of the input
listwill be between 0 and 1000 (inclusive). - The time complexity of your solution should be O(log n), where n is the length of the list.
Notes
- Implement a binary search algorithm to efficiently find the insertion point.
- Pay close attention to the difference between
bisect_leftandbisect_rightin how they handle existing elements equal tox. - Consider edge cases such as empty lists and elements smaller or larger than all elements in the list.
- You are not required to implement the entire
bisectmodule, only thebisect_leftandbisect_rightfunctions. - The list is not allowed to be modified. The functions should return the index where the element should be inserted.