Leetcode ☞ 35. Search Insert Position 【binary search 二分查找 模板】

35. Search Insert Position

My Submissions
Total Accepted: 95470  Total Submissions: 259096  Difficulty: Medium

Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.

You may assume no duplicates in the array.

Here are few examples.
[1,3,5,6], 5 → 2
[1,3,5,6], 2 → 1
[1,3,5,6], 7 → 4
[1,3,5,6], 0 → 0
















我的AC(4ms,前有34%):

<span style="font-size:18px;">int searchInsert(int* nums, int numsSize, int target) {
    int low = 0, high = numsSize - 1, mid;
    while(low <= high){
        if (nums[low] > target)
            return low;
        if (nums[high] < target)
            return high + 1;
        
        mid = low + (high - low) / 2;
        if (nums[mid] > target)
            high = mid - 1;
        else if (nums[mid] < target)
            low = mid + 1;
        else
            return mid;
    }
}</span>


思路:

二分查找 +  每次都先判断target是否在【nums[low] , nums[high]】之间,不在就说明是需要插入在边界处。




二分查找代码模板(理解+背):

要点有三:

1、使用(low+high)/2会有整数溢出的问题(当low+high的结果大于表达式结果类型所能表示的最大值时)【atoi那个题时也遇到超出INT_MAX的情况】
这样,产生溢出后再/2是不会产生正确结果的,而low+((high-low)/2)不存在这个问题

2、while循环时,有等号

3、mid跟target的判断时,没等号,执行时是加/减1



非递归:

int binarySearch(int* nums, int numsSize, int target) {
    int low = 0, high = numsSize - 1, mid;
    
    while(low <= high){
        mid = low + (high - low) / 2;
        
        if (nums[mid] > target)
            high = mid - 1;
        else if (nums[mid] < target)
            low = mid + 1;
        else
            return mid;
    }
    if(low > high)//没找到
        return -1;
}


递归实现:

int binary_search(int arr[],int low,int high,int key){
    int mid = low + (high - low) / 2;
	if(low > high)
		return -1;
	else{
        if(arr[mid] == key)
			return mid;
		else if (arr[mid] > key)
			return binary_search(arr, low, mid - 1, key);
		else
			return binary_search(arr, mid + 1, high, key);
    }
}


以下内容 整理自:http://blog.csdn.net/int64ago/article/details/7425727/


对num[]={1,2,2,4,4,8,10}不减序列在区间[0,7)进行查找。

我总结的二分无非就4种情况:YES_LEFT、YES_RIGHT、NO_LEFT、NO_RIGHT,分别代表:能找到且返回最左边的数的位置(如查找4的时候返回位置3)、能找到且返回最右边的数的位置(如查找4的时候返回位置4)、不能找到且返回左边与其接近的数的位置(如查找3的时候返回位置2)、不能找到且返回右边与其接近的数的位置(如查找3的时候返回位置3)。下面是我总结调试的代码:


对于YES_LEFT或者NO_RIGHT

int bSearch(int begin, int end, int e)  
{  
    int mid, left = begin, right = end;  
    while(left <= right)  
    {  
        mid = (left + right) >> 1;  
        if(num[mid] >= e) right = mid - 1;  
        else left = mid + 1;  
    }  
    return left;  
} 


对于YES_RIGHT或者NO_LEFT

int bSearch(int begin, int end, int e)  
{  
    int mid, left = begin, right = end;  
    while(left <= right)  
    {  
        mid = (left + right) >> 1;  
        if(num[mid] > e) right = mid - 1;  
        else left = mid + 1;  
    }  
    return right;  
} 


      不做过多说明,单步调试自然会发现执行过程,要说明的是,两个程序都用了right = mid - 1; left = mid +1;用这个的前提是终止条件要是left <= right。要注意的是,有的二分查找不是只需要四种情况中的一种,而是组合使用,比如查找一个数,如果找到则×××不然则×××,如果是YES_LEFT || NO_RIGHT组合或者YES_RIGHT || NO_LEFT组合就直接用上面代码即可,否则就要综合用了,加一些判断等说明,因为用的时候不多,就不给出代码了,自己如果遇到可以试着写写,当成模板,以后直接用~

       现在,是不是觉得二分查找很容易呢?如果总结过的话……


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 二分法 5 1.1. 什么是二分查找 5 1.2. 如何识别二分法 5 1.3. 二分法模板 6 1.3.1. 模板一 6 1.3.1.1. 模板代码 6 1.3.1.2. 关键属性 7 1.3.1.3. 语法说明 7 1.3.1.4. Lc69:x的平方根 8 1.3.1.5. Lc374:猜数大小 9 1.3.1.6. Lc33:搜索旋转数组 11 1.3.2. 模板二 13 1.3.2.1. 模板代码 13 1.3.2.2. 关键属性 14 1.3.2.3. 语法说明 14 1.3.2.4. Lc278:第一个错误版本 14 1.3.2.5. Lc162:寻找峰值 16 1.3.2.6. Lc153:寻找旋转排序数组最小值 19 1.3.2.7. Lc154:寻找旋转排序数组最小值II 20 1.3.3. 模板三 22 1.3.3.1. 模板代码 22 1.3.3.2. 关键属性 23 1.3.3.3. 语法说明 23 1.3.3.4. LC-34:在排序数组中查找元素的第一个和最后一个 23 1.3.3.5. LC-658:找到K个最接近的元素 25 1.3.4. 小结 28 1.4. LeetCode二分查找题目 29 2. 双指针 30 2.1. 快慢指针 31 2.1.1. 什么是快慢指针 31 2.1.2. 快慢指针模板 31 2.1.3. 快慢指针相关题目 32 2.1.3.1. LC-141:链表是否有环 32 2.1.3.2. LC-142:环形链表入口 34 2.1.3.3. LC-876:链表的中间节点 37 2.1.3.4. LC-287:寻找重复数 40 2.2. 滑动窗口 43 2.2.1. 什么是滑动窗口 43 2.1.4. 常见题型 44 2.1.5. 注意事项 45 2.1.6. 滑动窗口模板 45 2.1.7. 滑动窗口相关题目 46 2.1.7.1. LC-3:无重复字符的最长子串 47 2.1.7.2. LC-76:最小覆盖子串 49 2.1.7.3. LC-209:长度最小的子数组 54 2.1.7.4. LC-239:滑动窗口最大值 57 2.1.7.5. LC-395:至少有K个重复字符的最长子串 60 2.1.7.6. LC-567:字符串排列 62 2.1.7.7. LC-904:水果成篮 64 2.1.7.8. LC-424:替换后的最长重复字符 66 2.1.7.9. LC-713:乘积小于K的子数组 67 2.1.7.10. LC-992:K个不同整数的子数组 70 2.3. 左右指针 73 2.3.1. 模板 73 2.3.2. 相关题目 73 2.3.2.1. LC-76:删除倒数第N个节点 74 2.3.2.2. LC-61:旋转链表 76 2.3.2.3. LC-80:删除有序数组中的重复项 79 2.3.2.4. LC-86:分割链表 80 2.3.2.5. LC-438:找到字符串中所有字母的异位词 82 3. 模板 85 2.3.2.6. LC-76:删除倒数第N个节点 85
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值