【剑指Offer-53-I】在排序数组中查找数字 I
问题
统计一个数字在排序数组中出现的次数。
示例
输入: nums = [5,7,7,8,8,10], target = 8
输出: 2输入: nums = [5,7,7,8,8,10], target = 6
输出: 0
解答
class Solution {
public:
int search(vector<int>& nums, int target) {
if (nums.empty()) return 0;
int left = 0, right = nums.size() - 1;
while (left < right) { // 找等于target的起始点
int mid = (left + right) >> 1;
if (nums[mid] < target) left = mid + 1;
else right = mid;
}
if (nums[left] != target) return 0; // 此时代表数组中不含target
int start = left;
right = nums.size() - 1;
while (left < right) { // 找等于target的终止点
int mid = (left + right + 1) >> 1;
if (nums[mid] > target) right = mid - 1;
else left = mid;
}
return left - start + 1;
}
};
重点思路
这道题很好地锻炼了二分查找的细节。当我们需要一个数的左边界时,采用左指针右移的方式;当我们需要一个数的右边界时,采用右指针左移的方式。我不习惯在二分查找的过程中加任何等号比较。除此之外,mid
的取值也是有说法的。当else
中出现right = mid
时,mid
应该被初始化为(left + right) >> 1
;当else
中出现left = mid
时,mid
应该被初始化为(left + right + 1) >> 1
,这两个的区别在于,当数组长度为偶数时,mid
取的是中间靠左还是靠右的一个数。二分查找需要保证左右指针每次操作必定会变一个,否则就会无限循环下去。