资讯详情

资讯详情

千问 LeetCode 34. 在排序数组中查找元素的第一个和最后一个位置 Python3实现

LeetCode 34 在排序数组中查找元素的第一个和最后一个位置的 Python3 实现核心在于两次二分查找分别寻找目标元素的左边界和右边界。算法思路这道题考察的是二分查找的边界收缩寻找左边界当 nums[mid] target 时不立即返回而是收缩右边界right mid - 1继续向左半部分寻找。寻找右边界当 nums[mid] target 时收缩左边界left mid 1继续向右半部分寻找。注意由于我们在 nums[mid] target 时继续收缩边界最终 left 和 right 会越界或指向非目标元素。因此最后需要判断 left 或 right 是否合法且对应元素是否真的等于 target。Python3 代码实现class Solution:def searchRange(self, nums: List[int], target: int) - List[int]:def findLeft():left, right 0, len(nums) - 1while left right:mid (left right) // 2if nums[mid] target:left mid 1else:# 当 nums[mid] target 时收缩右边界right mid - 1# 循环结束时left 指向第一个等于 target 的位置return leftdef findRight(): left, right 0, len(nums) - 1 while left right: mid (left right) // 2 if nums[mid] target: right mid - 1 else: # 当 nums[mid] target 时收缩左边界 left mid 1 # 循环结束时right 指向最后一个等于 target 的位置 return right left_idx findLeft() right_idx findRight() # 边界检查如果 left_idx 越界或者对应元素不等于 target说明数组中不存在 target if left_idx len(nums) and nums[left_idx] target: return [left_idx, right_idx] return [-1, -1]执行流程图解以 nums [5,7,7,8,8,10], target 8 为例寻找左边界第一轮left0, right5, mid2nums[2]7 8 → left 3第二轮left3, right5, mid4nums[4]8 8 → right 3第三轮left3, right3, mid3nums[3]8 8 → right 2循环结束left3, right2left_idx 3 ✅寻找右边界第一轮left0, right5, mid2nums[2]7 8 → left 3第二轮left3, right5, mid4nums[4]8 8 → left 5第三轮left5, right5, mid5nums[5]10 8 → right 4循环结束left5, right4right_idx 4 ✅最终返回 [3, 4]。复杂度分析维度 复杂度 说明时间复杂度 O(log n) 执行了两次独立的二分查找空间复杂度 O(1) 只使用了常数级别的额外空间关键细节与易错点为什么最后检查 left_idx 而不是 right_idx因为 findLeft() 的逻辑保证了 left 最终会停在第一个 target 的位置。如果 target 不存在比如找 9left 可能会停在 10 的位置或者越界。只要 left_idx 合法且 nums[left_idx] target就一定能推导出 right_idx 也是合法的。合并写法在实际面试中为了节省代码量可以将两次二分合并为一个函数通过传入一个布尔值 isLeft 来决定收缩哪一边。但分开写可读性更好不易出错。掌握这种“遇到目标值不返回而是继续收缩边界”的二分思想可以秒杀所有求边界的二分题如 LeetCode 278 第一个错误的版本、LeetCode 35 搜索插入位置等。需要我帮你把这道题的合并写法单函数实现也写出来吗面试时写单函数会显得更精炼。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →