二分查找:目标值的最左下标 (bisect_left)
Leftmost Index via Binary Search (bisect_left)
开始编码某行情数据工程师维护一份有序事件日志:每条记录以整数序列号(例如自开盘起的微秒级时间戳)为键,按非递减顺序追加。回放工具经常需要回答「第一条键等于 T 的事件下标是多少?」——必须是最左侧的命中,这样下游消费者从该点开始连同所有相同键的重复条目一并回放。线性扫描在小规模可行,但日志里有 10⁵ 条记录、每次回放要查上千次。
请实现 solution(arr: list[int], target: int) -> int。返回最小(最左)的下标 i 使得 arr[i] == target;若 target 不在 arr 中则返回 -1。这正是 Python bisect.bisect_left 加一次存在性校验的语义。约束:arr 升序排列(允许重复),0 ≤ len(arr) ≤ 10⁵。
示例:solution([1, 3, 5, 7, 9, 11], 7) 返回 3——唯一命中在下标 3。solution([1, 2, 2, 2, 3, 4], 2) 返回 1——值 2 出现在下标 1、2、3,应返回最小的 1。solution([1, 3, 5, 7, 9], 4) 返回 -1——值 4 在排序上落在 3 和 5 之间,但不在数组中。
算法形态就是教科书的 bisect_left:维护一个半开区间 [lo, hi),每一步取 mid = (lo + hi) // 2。若 arr[mid] < target,答案严格在右半段,置 lo = mid + 1;否则(arr[mid] >= target),答案在 mid 或更左,置 hi = mid。当 lo == hi 循环终止——这个下标就是 target 可以插入的最左位置。再做一步 lo < len(arr) and arr[lo] == target 的检查,就能区分「找到」与「未找到」,分别返回 lo 或 -1。时间复杂度 O(log n),空间 O(1)。
约束条件
- 0 ≤ len(arr) ≤ 100000
- arr 升序排列(允许相等元素)
- 数值在标准 int 范围内;允许重复
- 若 target 不在 arr 中,返回 -1
- 若 target 出现多次,返回最小(最左)下标
样例
Case 1 · found, unique occurrence
输入: [[1,3,5,7,9,11],7]
期望: 3
7 在数组中只出现一次,位于下标 3。返回 3。
Case 2 · found with duplicates — return leftmost
输入: [[1,2,2,2,3,4],2]
期望: 1
目标值 2 出现在下标 1、2、3。题目要求返回最左侧(最小)下标,即 1,对应 bisect_left 的语义。
Case 3 · not found — returns -1
输入: [[1,3,5,7,9],4]
期望: -1
4 不在数组中(介于 3 和 5 之间)。按规定返回 -1。
最近提交
还没有提交记录。
编码区
实现 solution(...)。本地运行当前支持 Python 可见样例;服务端提交会运行可见样例和隐藏测试。
默认展示公开样例。点击「运行样例」后会在这里显示实际输出;点击「提交评测」会进入隐藏测试。
Case 1 · found, unique occurrence
输入: [[1,3,5,7,9,11],7]
期望: 3
7 在数组中只出现一次,位于下标 3。返回 3。
Case 2 · found with duplicates — return leftmost
输入: [[1,2,2,2,3,4],2]
期望: 1
目标值 2 出现在下标 1、2、3。题目要求返回最左侧(最小)下标,即 1,对应 bisect_left 的语义。
Case 3 · not found — returns -1
输入: [[1,3,5,7,9],4]
期望: -1
4 不在数组中(介于 3 和 5 之间)。按规定返回 -1。