← 返回编程题库
coding-binary-search-target-leftmost-bisect简单免费版2000ms未尝试

二分查找:目标值的最左下标 (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 可见样例;服务端提交会运行可见样例和隐藏测试。

加载编辑器...
计时0:00

默认展示公开样例。点击「运行样例」后会在这里显示实际输出;点击「提交评测」会进入隐藏测试。

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。