代码随想录学习第一天–二分查找
标准二分查找
给定数组array[n], 目标元素target
- 数组生序/降序排列。
- 无重复元素。
重点(升序):注意区间的定义,[left,right)还是[left,right]。
- [left,right)中left=right无意义,故循环结束条件为left==right。
其中当array[mid]<target, 则 left=left+1;
当array[mid]==target, 则找到target;
当array[mid]>target, 则right=mid;这是由于array[mid]已经被排除,故新的区间不包括mid,即[left,mid)。 - [left,right]中left=right有意义,故循环结束条件为left<right。
其中当array[mid]<target, 则 left=left+1;
当array[mid]==target, 则找到target;
当array[mid]>target, 则right=mid-1;这是由于array[mid]已经被排除,故新的区间不包括mid,即[left,mid-1]。
有重复元素的二分查找
给定数组array[n], 目标元素target,查找第一次出现target的位置。或者最后一次出现target的位置。
第一次出现target的位置
注意array[mid]==target时,不再跳出循环,而是继续从mid左侧查找target。
1.区间[left,right]中left=right有意义,故循环结束条件为left<right。
其中当array[mid]<target, 则 left=left+1;
当array[mid]==target, right=mid-1;(target已经出现,需要在mid左侧继续寻找)
当array[mid]>target, 则right=mid-1;这是由于array[mid]已经被排除,故新的区间不包括mid,即[left,mid-1]。
最终的left指向的位置为第一次出现target的位置。
最后一次出现target的位置
注意array[mid]==target时,不再跳出循环,而是继续从mid左侧查找target。
1.区间[left,right]中left=right有意义,故循环结束条件为left<right。
其中当array[mid]<target, 则 left=left+1;
当array[mid]==target, left=mid+1;(target已经出现,需要在mid左侧继续寻找)
当array[mid]>target, 则right=mid-1;这是由于array[mid]已经被排除,故新的区间不包括mid,即[left,mid-1]。
最终的left指向的位置为第一次出现target的位置。
转换
查找整数,最后一次出现target的位置 等于 第一次出现target+1的位置-1,可以将最后一次出现target的位置使用第一次出现target的位置的代码计算,以实现代码复用。
leetcode题目
35.搜索插入位置 (opens new window)
34.在排序数组中查找元素的第一个和最后一个位置 (opens new window)
69.x 的平方根
367.有效的完全平方数
代码示例
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n) 的算法。
示例 1:
输入: nums = [1,3,5,6], target = 5
输出: 2
示例 2:
输入: nums = [1,3,5,6], target = 2
输出: 1
示例 3:
输入: nums = [1,3,5,6], target = 7
输出: 4
来源:力扣(LeetCode)
链接:[https://leetcode.cn/problems/search-insert-position]
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。*/
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
//二分查找搜索位置;注意区间的定义的不同需要判断的条件不同。
//[left,right) left=mid+1,right=mid; while(left<right)
//初始化left=0;rightright=nn;
//mid= (left+right) /2;若最终未找到即[left right+1)->[left,left)
//看numss[left]与target的大小决定插入左边还是右边(实际不可能出现在右边)
int right=nums.size();
int left=0;
while(left<right)
{
int mid=(left+right)/2;
if(nums[mid]==target) return mid;
else if(nums[mid]<target)
{
left=mid+1;
}
else
{
right=mid;
}
}
return left;
}
};`