Leetcode刷题笔记 35.搜索插入位置(详细说明二分查找)

35. 搜索插入位置


时间:2020年7月17日
知识点:二分查找
题目链接: https://leetcode-cn.com/problems/search-insert-position/

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

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

示例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. 是二分查找问题,但是又有所不同
  2. 二分查找有两种模版
  3. 在循环体内查找目标元素,把区间分成三份
    [mid] return
    [left,mid-1] end = mid-1
    [mid+1,right] left = mid+1
	int searchInsert(vector<int>& nums, int target) {
	   int len = nums.size();
	   int left = 0;
	   int right = len - 1;
	   while (left <= right) {
	       int mid = left + (right - left) / 2;
	       //int mid = (left + right) / 2; right和left很大时可能会溢出
	       if (nums[mid] == target) {
	           return mid;
	       } else if (nums[mid] < target) {
	           left = mid + 1;
	       } else {
	           right = mid - 1;
	       }
	   }
	   return -1;
	}
  1. 在循环体内排除一定不存在目标答案的区间,把区间分成两份,考虑中间元素[mid]在什么情况下一定不是目标元素
    1. [left,mid] right = mid
      [mid+1,right] left = mid+1
	//(本题就是这个情况,target < nums[mid] 时一定不是解)
	int searchInsert(vector<int>& nums, int target) {
	    int left = 0;
	    int right = nums.size()-1;
	    while(left<right)
	    {
	        int mid = left+(right-left)/2;
	        if (nums[mid]==target)
	           return mid;
	        else if(check(mid))
	           left = mid+1;
	        else
	           right = mid;
	    }
	return left;
	}
  1. [left,mid-1] right = mid-1
    [mid,right] left = mid
    有可能陷入死循环 只有看到 left = mid 的时候,才需要调整成为上取整,
    nums[0]=0 nums[1]=5
    left = 0 right = 1 mid = first+(end-first)/2 = 0 求
    left = mid right不变 陷入死循环
    解决方法 mid = first+(end-first+1)/2 = 1
	int searchInsert(vector<int>& nums, int target) {
	     int left = 0;
	     int right = nums.size()-1;
	     while(left<right)
	     {
	         int mid = left+(right-left+1)/2;
	         if (nums[mid]==target)
	            return mid;
	         else if(check(mid))
	            left = mid;
	         else
	            right = mid-1;
	     }
	     return left;
	 }
  1. 这里要求的是大于等于 target 的第 1 个元素的位置。

代码

#include <stdio.h>
#include <vector>
#include <iostream>
using namespace std;

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int n = nums.size();
        int left = 0;
        int right = n - 1; // 定义target在左闭右闭的区间里,[left, right] 
        while (left <= right) { // 当left==right,区间[left, right]依然有效
            int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2
            if (nums[middle] > target) {
                right = middle - 1; // target 在左区间,所以[left, middle - 1]
            } else if (nums[middle] < target) {
                left = middle + 1; // target 在右区间,所以[middle + 1, right]
            } else { // nums[middle] == target
                return middle;
            }
        }
        // 分别处理如下四种情况
        // 目标值在数组所有元素之前  [0, -1]
        // 目标值等于数组中某一个元素  return middle;
        // 目标值插入数组中的位置 [left, right],return  right + 1
        // 目标值在数组所有元素之后的情况 [left, right], return right + 1
        return right + 1;
    }
};
/*
class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int n = nums.size();
        int left = 0;
        int right = n; // 定义target在左闭右开的区间里,[left, right)  target
        while (left < right) { // 因为left == right的时候,在[left, right)是无效的空间
            int middle = left + ((right - left) >> 1);
            if (nums[middle] > target) {
                right = middle; // target 在左区间,在[left, middle)中
            } else if (nums[middle] < target) {
                left = middle + 1; // target 在右区间,在 [middle+1, right)中
            } else { // nums[middle] == target
                return middle; // 数组中找到目标值的情况,直接返回下标
            }
        }
        // 分别处理如下四种情况
        // 目标值在数组所有元素之前 [0,0)
        // 目标值等于数组中某一个元素 return middle
        // 目标值插入数组中的位置 [left, right) ,return right 即可
        // 目标值在数组所有元素之后的情况 [left, right),return right 即可
        return right;
    }
};
*/
int main()
{
    vector<int> v(4,0);
    v[0]=1;v[1]=3;v[2]=5;v[3]=6;
    vector<int> w(3,0);
    w[0]=1;w[1]=3;w[2]=5;
    vector<int> z(1,0);
    z[0]=1;
    Solution s;
    cout<<s.searchInsert(v,2);
}

今天也是爱zz的一天哦!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值