【优化王牌】二分查找

二分查找

   二分法?多简单?NO!NO!NO!我们可不是讲俗透顶的二分查找!我们讲的是二分查找的应用!

     我们讲的也不是二分答案,是优化。

     你真的会充分地用二分查找吗?

     事实告诉你:含序列题目并可以暴力等求出答案的,基本上二分查找都是可以将其优化的!

     不信?咱们来看看一道简单的排序:

MZA 的排序

【问题描述】  

现在知道 MZA 有一堆同学,也不知道有多少个。

可恶的 MZA 现在给了你这堆同学的名字和成绩(都是英文名字),请你输出他们的成绩排序。每个人一行,先输出名字,然后输出成绩。

然后 MZA 就不乐意了。

【输入格式】  

每行先是名字,然后是分数
数据以“end -100"结尾

【输出格式】  

每行先是名字,然后是分数

【输入样例】    

WXJ 99
THC 20
YSM 100
SWQ 50
CC 59
LJX 10
YSF 0
end -100

【输出样例】

YSM 100
WXJ 99
CC 59
SWQ 50
THC 20
LJX 10
YSF 0

【数据规模与约定】

保证名字不超过 100个字符。
成绩都是不超过 100 的正整数。
保证不超过 1000 个同学
数据保证没有人分数相同

【试题分析】

这么简单!直接冒泡O(n^2)不就得啦!

但要是数据范围大一点或时间少一点不就完了吗?而且冒泡排序交换时还需要O(len)来复制呢~~

所以要想在上面前提下AC,我们就可以用到二分查找。

怎么找呢?

1.把输入的序列存两个数组。

2.把A数组排序(随便你用sort,qsort,mergesort……只要别用冒泡就行了)

3.每次都找b[0~n-1]在现在的A数组里面的下标。

4.找到下标以后,直接复制给anschar相应下标即可

5.直接输出

有没有发现,找下标时总可以用到二分法优化一下。

所以优化后的复杂度为O(nlogn)

【代码】

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int a[1001],b[1001];
char anschar[1001][110],in[1001][110];
int bsearch(int x,int n)
{
	int left=0,right=n-1;
	while(left<=right)
	{
		int mid=(left+right)/2;
		if(a[mid]==x) return mid;
		else if(a[mid]>x) left=mid+1;//因为我们是从大往小排,所以切记不要忘了该符号
		else right=mid-1;
	}
	return -1;
}
bool cmp(int a,int b)
{
      return a>b;
}
int main()
{
	int i=0;
	while(cin>>in[i]>>a[i]&&a[i]!=-100&&strcmp(in[i],"end")!=0) b[i]=a[i],i++;
	sort(a,a+i,cmp);//从大往小排
	for(int j=0;j<i;j++)
	{
		int tmp=bsearch(b[j],i);//找原来输入的每个数在A数组里的下标
		strcpy(anschar[tmp],in[j]);//直接复制
	}
	for(int j=0;j<i;j++) cout<<anschar[j]<<" "<<a[j]<<endl;//直接输出
}

这就是优化的思想,也是非常有用的一类思想。

大家还可以看这道题:

http://www.cnblogs.com/wxjor/p/5793222.html

时间: 2024-08-09 06:33:25

【优化王牌】二分查找的相关文章

快速排序和二分查找

快排和二分查找都基于一种叫做「分治」的算法思想,通过对数据进行分类处理,不断降低数量级,实现O(logN)(对数级别,比O(n)这种线性复杂度更低的一种,快排核心是二分法的O(logN),实际复杂度为O(N*logN))的复杂度. 快速排序 快排大概的流程是: 随机选择数组中的一个数 A,以这个数为基准 其他数字跟这个数进行比较,比这个数小的放在其左边,大的放到其右边 经过一次循环之后,A 左边为小于 A 的,右边为大于 A 的 这时候将左边和右边的数再递归上面的过程 const Arr = [

二分查找与 bisect 模块

Python 的列表(list)内部实现是一个数组,也就是一个线性表.在列表中查找元素可以使用 list.index() 方法,其时间复杂度为O(n).对于大数据量,则可以用二分查找进行优化.二分查找要求对象必须有序,其基本原理如下: 1.从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜素过程结束: 2.如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较. 3.如果在某一步骤数组为空,则代表找不到. 二分查找也成为折半查找,

二分查找法优化插入排序

通俗的插排是对一个整型数组进行升序排序,可以看出每个元素插入到队列中经过两个步骤:先是挨个比较,找到自己所在的位置:然后把后面的数据全部移位,然后把元素插入. 要把数据插入,移位是必不可少了.那么,挨个比较倒是可以优化,因为要插入的队列已经是排序好的,我们可以使用二分法来减少比较的次数. 二分法的时间复杂度为O(log 2 n),而线性查找的复杂度为O(n). 在对50000个随机数进行测试比较中,发现加了二分查找的插排比普通的插排速度快了将近一倍!(通俗插排7888ms,优化插排4852ms)

优化的直接插入排序(二分查找插入排序,希尔排序)

直接插入排序 (一)概念及实现 直接插入排序的原理:先将原序列分为有序区和无序区,然后再经过比较和后移操作将无序区元素插入到有序区中. 具体如下(实现为升序): 设数组为a[0…n]. 1.        将原序列分成有序区和无序区.a[0…i-1]为有序区,a[i…n] 为无序区.(i从1开始) 2.        从无序区中取出第一个元素,即a[i],在有序区序列中从后向前扫描. 3.        如果有序元素大于a[i],将有序元素后移到下一位置. 4.        重复步骤3,直到找

集训第四周(高效算法设计)N题 (二分查找优化题)

原题:poj3061 题意:给你一个数s,再给出一个数组,要求你从中选出m个连续的数,m越小越好,且这m个数之和不小于s 这是一个二分查找优化题,那么区间是什么呢?当然是从1到数组长度了.比如数组长度为10,你先找5,去枚举每一个区间为5的连续的数,发现存在这样的数,那么就可以继续往左找,反之则往右找,直到左右区间重合,即为正确答案,(有可能是右区间小于左区间,所以每次都应该求区间中点值) #include"iostream" #include"set" #incl

集训第四周(高效算法设计)B题 (二分查找优化题)

---恢复内容开始--- Description Before the invention of book-printing, it was very hard to make a copy of a book. All the contents had to be re-written by hand by so calledscribers. The scriber had been given a book and after several months he finished its

python算法之二分查找

说明:大部分代码是在网上找到的,好几个代码思路总结出来的 通常写算法,习惯用C语言写,显得思路清晰.可是假设一旦把思路确定下来,并且又不想打草稿.想高速写下来看看效果,还是python写的比較快.也看个人爱好.实习的时候有个同事对于python的缩进来控制代码块各种喷....他认为还是用大括号合适...怎么说呢,适合自己的才是最好的.我个人的毛病就是,写了几天C,到要转到python的时候,代码中依旧有C的影子..比方大括号问题,比方忘记在while或这for.if.else等后面加":&quo

Java学习之二分查找算法

好久没写算法了.只记得递归方法..结果测试下爆栈了. 思路就是取范围的中间点,判断是不是要找的值,是就输出,不是就与范围的两个临界值比较大小,不断更新临界值直到找到为止,给定的集合一定是有序的. 自己写的代码: 1 package com.gh; 2 3 import java.util.Arrays; 4 /** 5 * 二分查找算法实现 6 * @author ganhang 7 * 8 */ 9 public class Search { 10 public static void mai

二分查找如何“花式”卖萌

二分查找,敢说这货埋在土里化到灰里应该都是认得的.其原理思想也是如此的简单明了,敲代码时都懒得经过反射弧.但事实上,据Knuth神犇描述,第一个木有bug的二分查找是这个算法发表之后12年在出现,但后来发现还是存在一些数组越界的小问题.而如今,我们大都是开门见山的学习被前辈们优化证明的算法,这也是“牛逼顿”所谓的站在巨人的肩膀上,却也如此. 回头来看二分查找如何“花式”卖萌. Problem:给定一个有序数组A,且数组中的元素存在重复,各大一个目标值target,求目标值在数组的的下标的区间(即