LeetCode 热题 HOT 100 第18天:“在排序数组中查找元素的第一个和最后一个位置”

继续刷LeetCode 热题 HOT 100 的题目,并且在博客更新我的solutions。在csdn博客中我会尽量用文字解释清楚,相关Java代码大家可以前往我的个人博客jinhuaiyu.com中查看。
题目:在排序数组中查找元素的第一个和最后一个位置
给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
进阶:
你可以设计并实现时间复杂度为 O(log n) 的算法解决此问题吗?
示例 1:
输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]
示例 2:
输入:nums = [5,7,7,8,8,10], target = 6
输出:[-1,-1]
示例 3:
输入:nums = [], target = 0
输出:[-1,-1]
提示:
0 <= nums.length <= 105
-109 <= nums[i] <= 109
nums 是一个非递减数组
-109 <= target <= 109

solution:二分查找
今天的题看到有序数组和O(log n)复杂度,又要祭出二分查找了。和简单的二分查找稍微有点不同,但整体思路还是每次去掉一半,对另一半继续查找。
我们先来分析如何二分查找升序有重复数组中第一次出现target的位置。
整个二分架构和正常的基本上一样,但是不对mid进行单独处理,而是把它归到其中一侧中在下次搜索时继续。这里的mid因为int除法的特殊性,当当前搜索数量为偶数时,会向下取整。
这里循环条件应该是start < end,不能取等号,不然后面会死循环。如果nums[mid] < target,此时res如果存在,一定在右侧(不包括mid);如果target <= nums[mid],此时res如果存在,一定在左侧(包括mid)。由于后面一种情况不再是end = mid-1,而是直接end = mid,如果start = end的循环也处理的话,将无限循环。因此当start = end时就应该直接结束循环。结束循环后判断start处是否等于target,如果等于,说明找到了,如果不等于,说明不存在target,返回-1。
而对于二分查找升序有重复数组中最后一次出现target的位,其实大家可以想象成前面是从左往右找第一个target,现在是从右往左找target,所有的条件对称修改即可。但有一点要注意,前面计算mid时直接采用int的向下取整除法mid = (end + start) / 2,现在对称过来,对于偶数则应该向上取整:mid = (end + start + 1) / 2。
最后,如果原始数组为空,就不要搜索直接返回{-1,-1}就好了。

Finally,带有详细注释的代码放在我的个人博客http://jinhuaiyu.com/leetcode-find-first-and-last-position-of-element-in-sorted-array/

你可能感兴趣的:(LeetCode,leetcode,算法,二分查找)