题目:https://leetcode-cn.com/problems/search-insert-position/
思路一:二分法查找(在循环体的内部查找元素
分析:
因为是一个有序数组,先找到中间位置,(注意,如果是偶数,中间位置选用左边的),然后用中间位置的值和目标值进行比较,如果比目标值大,就在数 组中间值左半部分找,反之,进在右半部分找;如果和目标值相等,就返回下标,直到指向右边位置的指针(low)大于指向左面位置的指针(high),就结束 (说 明数组里面没有和目标值相同的值);这就会出现三种情况:目标值比数组的最大值大,这时low的值大于数组的长度-1;目标值比数组的最小值小, 这 时high比0小;目标值位于数组中两个元素中间,这时low的范围在【0,len-1】之间,low的位置就是插入的位置。
即归结为四种情况:
-
目标值在数组所有元素之前
-
目标值等于数组中某一个元素
-
目标值插入数组中的位置
-
目标值在数组所有元素之后
步骤:
1、定义两个变量分别指向数组的左右两个端点(用于表示查找的范围)
2、如果右端点小于等于左端点,就执行循环体
3、计算数组的中点值的下标,如果中间值比目标值小,则右端点等于中间值的下标+1;如果中间值比目标值大,则将左端点的值等于中间值的下标-1;否则,就 返 回(中间值和目标值相等),就返回下标
4、如果执行完循环体没有找到中间值和目标值相等的下标,则low>high;如果右下标比数组的最后一位元素的下标大(目标值比数组的最大的值大),则返回数 组 的最后一位元素的下标+1(数组的长度);如果左端点比0小(目标值比数组0号位置的数小),则返回数组的0号位置;否则(目标值在数组的两个元素之 间),给返回low;
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int len = nums.size();
//采用左闭右闭的区间
int low = 0;//指向数组的左右边
int high = len-1;//指向数组的最左面
while (low <= high)
{
int midaum =high+(high-low)>>1
if (nums[midaum] < target)
{
low = midaum + 1;
}
else if (nums[midaum] > target)
{
high = midaum - 1;
}
else
{
return midaum;
}
}
if (low>len-1)
{
return len ;
}
else if(high<0)
{
return 0;
}
else
{
return low;
}
}
};
思路二:二分法
分析:
int searchInsert(vector<int>& nums, int target) {
int len = nums.size();
int low = 0;
int high = len-1;
int ans=len;
while (low <= high)
{
int mid=((high-low)>>1)+low;
if(target<=nums[mid])
{
ans=mid;
high=mid-1;
}
else
{
low=mid+1;
}
}
return ans;
}
思路三:二分法(在 循环体内部排除元素)
-
while(left < right) 这种写法表示在循环体内部排除元素;
-
退出循环的时候 left 和 right 重合,区间 [left, right] 只剩下成 1 个元 素,退出循环,这个元素 有可能
就是我们要找的元素。 -
采用左闭右闭的区间
int searchInsert(vector<int> &nums, int target) {
int size = nums.size();
if (size == 0) {
return 0;
}
// 特判
if (nums[size - 1] < target) {
return size;
}
int left = 0;
int right = size - 1;
while (left < right) {
int mid = left + (right - left) / 2;
// 严格小于 target 的元素一定不是解
if (nums[mid] < target) {
// 下一轮搜索区间是 [mid + 1, right]
left = mid + 1;
}
else {
// 下一轮搜索区间是 [left, mid]
right = mid;
}
}
return left;
}