编程之美之二分查找总结

二分查找原理很简单,但是边界条件容易出错,出现死循环等,要想彻底分清楚,应该要理解透彻,大家可以用先思考,然后用例子来验证,下面是我的思路,如果有错误,请指正。我们先看变形一:如果有很多待查找的数字,找出最大的,所以最大的一定是在最右边,为了能够把左右两个数进行对比,循环结束的时候,左右指针对应的数要相隔1,所以循环结束的条件是left < right -1;要想保留最大下标,当data[mid] == value时,不能结束,因为data[mid+1]也可能等于value,所以要继续遍历,这时让left
= mid,所以小于和等于要合并。变形二类似。再看变形三:为了找data[i]<value的最大i,当data[i]==value时也不能结束,此时,由于i肯定是在等于value的那个下标的左边,所以当data[i]==value时,要把right = mid继续遍历,即把大于和等于合并,而此时和变形一不同的时,要找的是小于,而不是等于,所以当data[i]>=value时,结果肯定在i的左边,不可能包括i,所以right = mid -1而不是mid,变形四类似。

标准的二分查找一:

int biSearch(vector<int>& data,int value)
{
	int left = 0,right = data.size()-1;//注意1
	while(left <= right)//注意2
	{
		int mid = left + ((right - left) >> 1);//注意3
		if(data[mid] < value)left = mid + 1;
		else if(data[mid] > value)right = mid - 1;//注意4
		else return mid;
	}
	return -1;
}

标准的二分查找二(不常用):

int biSearch(vector<int>& data,int value)
{
	int left = 0,right = data.size();//注意1
	while(left < right)//注意2
	{
		int mid = left + ((right - left) >> 1);
		if(data[mid] < value)left = mid + 1;
		else if(data[mid] > value)right = mid;//注意3
		else return mid;
	}
	return -1;
}

变形一:如果有多个满足条件,返回序号最大的

int biSearch(vector<int>& data,int value)
{
	int left = 0,right = data.size()-1;//注意1
	while(left < right - 1)
	{
		int mid = left + ((right - left) >> 1);
		if(data[mid] <= value)left = mid;//注意2
		else right = mid;//注意3
	}
	if(data[right] == value)return right;
	if(data[left] == value)return left;
	return -1;
}

变形二:如果有多个满足条件,返回序号最小的

int biSearch(vector<int>& data,int value)
{
	int left = 0,right = data.size()-1;//注意1
	while(left < right - 1)
	{
		int mid = left + ((right - left) >> 1);
		if(data[mid] >= value)right = mid;//注意2
		else left = mid;//注意3
	}
	if(data[left] == value)return left;
	if(data[right] == value)return right;
	return -1;
}

变形三:求最大的i,使得data[i] < value

int biSearch(vector<int>& data,int value)
{
	int left = 0,right = data.size()-1;//注意1
	while(left < right - 1)
	{
		int mid = left + ((right - left) >> 1);
		if(data[mid] < value)left = mid;//注意2
		else right = mid-1;//注意3
	}
	if(data[right] < value)return right;
	if(data[left] < value)return left;
	return -1;
}

变形四:求最小的i,使得data[i] > value

int biSearch(vector<int>& data,int value)
{
	int left = 0,right = data.size()-1;//注意1
	while(left < right - 1)
	{
		int mid = left + ((right - left) >> 1);
		if(data[mid] > value)right = mid;//注意2
		else left = mid + 1;//注意3
	}
	if(data[left] > value)return left;
	if(data[right] > value)return right;
	return -1;
}

编程之美之二分查找总结

时间: 2024-10-06 00:59:08

编程之美之二分查找总结的相关文章

养成良好的编程风格--论二分查找的正确姿势

摘自:http://www.cnblogs.com/ider/archive/2012/04/01/binary_search.html 在学习算法的过程中,我们除了要了解某个算法的基本原理.实现方式,更重要的一个环节是利用big-O理论来分析算法的复杂度.在时间复杂度和空间复杂度之间,我们又会更注重时间复杂度. 时间复杂度按优劣排差不多集中在: O(1), O(log n), O(n), O(n log n), O(n2), O(nk), O(2n) 到目前位置,似乎我学到的算法中,时间复杂度

编程算法 - 快速排序(QuickSort)和二分查找(BinarySearch)

快速排序(QuickSort)和二分查找(BinarySearch) 本文地址: http://blog.csdn.net/caroline_wendy 快速排序和二分查找的定义, 网上书上都有, 本文主要是讲解如何写出这两个经典算法. 程序员必须掌握的两种算法, 使用任何语言, 使用纸都是必须的. 快速排序(C): /* * main.cpp * * Created on: 2014年9月10日 * Author: Spike */ #include <stdio.h> #include &

leetcode&amp;编程之美——博文目录

leetcode刷题整理: 1——Two Sum(哈希表hashtable,map) 2——Add Two Numbers(链表) 3——Longest Substring Without Repeating Characters(set,哈希表,两个指针) 9——Palindrome Number (数学问题) 11——Container With Most Water(两个指针) 12——Integer to Roman(string,数学问题) 13——Roman to Integer(s

【编程之美】中的美中不足,谈谈我的理解

拿到书本后,看了一下,里面的题目并不是太难,都是初级算法,或者有些根本就不用到算法. 在二分查找的知识点中,还是比较新颖的,看来我写的二分一直存在bug啊.在看看其他方面的题目,很多题目还是要总结分享一下的, 第三章的题目全部看完了,自己也写了一下程序进行了优化.部分作者的程序没有看~cpp的变量名太长了,又不是写项目啊~自己添加的名字估计自己以后看比较方便,对于读者来说,估计作用并不是太大.不如写成伪算法,这样更好一点啊.对吧~~~~~~ 话说这个完全可以用二进制编程来处理.具体的二进制编程技

编程之美——longest incremental sequence(LIS)

解法一:通过遍历得到(0:i)的LIS,时间复杂度O(N^2): 具体思路于代码,如下: 1 #include<iostream> 2 #include<vector> 3 using namespace std; 4 5 int longSub(int arr[],int n); 6 7 int main() 8 { 9 int arr[8]={1,-1,2,-3,4,-5,6,-7}; 10 cout<<longSub(arr,8)<<endl; 11

二分查找编码套路

二分查找的思想很好理解,但要写出没有bug的代码却并不是件容易的事.对于有序数组的二分查找,可以遵循一些套路快速写出无错代码. 下面先给出二分查找有序数组的一些问题,所有问题参考了<编程之美>. 1.给定非降序数组A,求任意一个i使得A[i]等于target,如不存在则返回-1. 2.给定非降序数组A,求最小的i使得A[i]等于target,如不存在则返回-1. 3.给定非降序数组A,求最大的i使得A[i]等于target,如不存在则返回-1. 4.给定非降序数组A,求最小的i使得A[i]大于

P2075 [NOIP2012T5]借教室 区间更新+二分查找

P2075 [NOIP2012T5]借教室 时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 noip2012-tg 描述 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室.教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样.面对海量租借教室的信息,我们自然希望编程解决这个问题.我们需要处理接下来n天的借教室信息,其中第i天学校有ri个教室可供租借.共有m份订单,每份订单用三个正整数描述,分别为dj,s

二分查找实现(Jon Bentley:90%程序员无法正确实现)

二分查找实现(Jon Bentley:90%程序员无法正确实现)作者:July出处:结构之法算法之道引言Jon Bentley:90%以上的程序员无法正确无误的写出二分查找代码.也许很多人都早已听说过这句话,但我还是想引用<编程珠玑>上的如下几段文字:“二分查找可以解决(预排序数组的查找)问题:只要数组中包含T(即要查找的值),那么通过不断缩小包含T 的范围,最终就可以找到它.一开始,范围覆盖整个数组.将数组的中间项与T 进行比较,可以排除一半元素,范围缩小一半.就这样反复比较,反复缩小范围,

算法学习一~分治法~二分查找,快速的找~

现在编程也算是走上门了,但是没有把算法掌握下来只能说自己还是门外汉,所以以后我们就开始努力的学习算法,现在把自己每天的学习分享在这里希望大家能喜欢,并且我也要在这里整理我一天的学习和思路,. 二分查找..大家经常需要在一个数组中寻找某个值.如果是一个已经拍好序的话那么可以很快的找到.我们考虑下暴力查找,就是a[n],中找一个m,那么最好时是o(1),最差时是0(n),最终平均情况就是长度n/2.这样的时间复杂度不算很高但是可以改进到logn的级别. 1 #include<stdio.h>//算