35. 搜索插入位置(C++ / C语言)---二分法查找

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

你可以假设数组中无重复元素。

示例 1:
输入:
[1,3,5,6], 5
输出: 2


示例 2:
输入:
[1,3,5,6], 2
输出: 1

示例 3:
输入: [1,3,5,6], 7
输出: 4

示例 4:
输入: [1,3,5,6], 0
输出: 0

 

——题目难度:简单


 





分析

有序数组中查找插入元素的位置,二分查找显然适用。大致思路是:在循环的过程中,不断排除不需要的解,最后剩下的那个元素的位置就一定是插入元素的位置。也就是使用二分法来达到「排除法」的效果。

1.当 nums 中没有元素时,直接返回 0 
2.当目标值大于 nums 里的最大值,则说明需要将其插入到数组的末尾,所以直接返回 nums.size()
3.当1 ,2的情况都不符合,那就说明需要查找的目标索引在区间 [0, nums.size() - 1] 内

  • 如果 target > nums[mid],因为严格小于 target 的元素一定不是解,所以可以排除掉区间 [left, mid] ,也就是可以设置下一轮的搜索区间为 [mid + 1, right] 
  • 如果 target <= nums[mid] ,如果 target == nums[mid] 的话,说明 mid 就是目标索引、如果 target < nums[mid] 的话,mid 则有可能是目标索引(当nums中没有target时)。综上所述,当 target <= nums[mid] 时,因为严格大于等于 target 的元素有可能是解,所以可以设置下一轮的搜索区间为 [left, mid],也就是可以排除掉区间 [mid + 1, right]。
  • 这样不断缩小区间后,肯定会缩小到只有一个元素的区间的时候(left == right),也就是找到了目标索引(是left,因为计算 mid 是下取整)

4.直接返回 left 即可。


-下面代码(C++)

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int n = nums.size();
        if (n == 0) return 0;
        
        /*如果目标值大于 nums 里的最大值,则将其插入到数组的末尾*/ 
    	if (target > nums[n-1]) return n;
    	
    	/*将在区间 [0, n - 1] 内查找目标索引*/ 
    	int left = 0, right = n - 1; 
    	while (left < right) {
    		int mid = left + (right - left) / 2; 
    		if (target > nums[mid]) { //严格小于 target 的元素一定不是解 
    			//下一轮搜索区间是 [mid + 1, right] 
    			left = mid + 1;
    		} else { //严格大于等于 target 的元素有可能是解
				//下一轮搜索区间是 [left, mid] 
    			right = mid;
    		}
    	}
    	
    	return left;
    }
};



 




C语言实现的代码 和 上述的分析思路有所不同,但其二分法的核心不变。

-下面代码(C语言)

//二分法
int searchInsert(int* nums, int numsSize, int target){
    int left = 0, right = numsSize-1,middle;
    while(right>=left)
    {
        middle = (left+right)/2;
        if(nums[middle]==target){
            return middle;
        }else if(nums[middle]>target){
            right = middle-1;
        }else{
            left = left+1;
        }
    }
    return left;
}

 

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

重剑DS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值