寒假之搜索(不是dfs/bfs)

线性搜索 二分搜索 借助STL标准库 进行搜索

1.线性搜索听名字就是以线的方式来遍历,直接从头到尾开始遍历,找到就找到,找不到就找不到。复杂度是O(n)。主要有两种方式来实现。

a:

bool linesearch(int *a,int num,int n)
{
	int i=0;
	a[n]=num;
	while(a[i]!=num)
		i++;
	if(i==n)
		return false;   //没有找到 
	
	return true;   		//找到了 
}

b:

bool linesearch(int *a,int num,int n)
{
	int i=0;
	for(i=0;i<=n;i++)
	{
		if(a[i]==num)
		{
			return false;
		}
	} 
	return false;
}

2.二分搜索,复杂度为O( log(n) ),在一些数据量大的时候,可以用二分搜索。

bool binary(int laft,int right,int num)
{
	paixu();  //需要先排序,可以用一下 sort 
	while(left<right)
	{
		int mid=(left+right)/2;
		if(a[mid]==num)
			return true;
		else if(a[mid]>num)
			right=mid;
		else if(a[mid]<num)
			left=mid+1;
	}
		 
	return false;
}

 二分搜索在一些题目上,有很多的变形,例如二分答案(二分加贪心的升级问题),对于区间的把握程度有很大的要求,需要多练习相关的题目,我下面讲讲具体的怎么处理问题的。

1.在大数据的情况下查找满足条件的数(前提是数据都是有序的),将区间一分为二,先判断中间值与查找数之间的大小关系,在左边那就继续在左边查找,在右边就相反操作。在不断的查找过程中,left 和 right  都是在不断的更新,当left 和 right 相等或者 left 大于 right 时,这时就不能再一分为二了。如果还没有查找到,就是真的没有;在二分的过程中,如果找到,就直接 return  掉。 这个left 和 right 如何变 根据题目的要求。

2.二分答案题型,属于难度提高题目,常常与贪心一起出现,不是仅仅二分数据,而是不断二分满足的答案,直到找到满足最优解的答案。(比如两者之间尽可能小的(间距)最大值或者最小值),这就要先满足 1 条件(尽可能小),然后再满足的二个条件是最大值和最小值 。这个就是二分答案,在不断的二分答案,找到最优的解。通常二分与很多算法都在一起使用,比如贪心等算法。就在二分过程当中判断此时答案是否符合标准,再进一步优化找到最优解。

POJ 2456 3273 2976 3122 1505 2018 HDU 5248 4004  2899 1969 4334 6383  洛谷1182 1824 noip 2012  CF 923B  

部分二分答案习题,自己可以练习。

 

看道例题:

 

给你一个n个整数序列和一个不同的q个整数序列t。写一个程序,输出c,t中的整数个数,也在集合s中。 

输入              

在第一行给出n。在第二行中,给出n个整数。第三行中给出了q。然后,在第四行中,给出q整数。

输出              

在一行中输出c。

约束条件              

s中的元素按升序排序

  • n ≤ 100000
  • q ≤ 50000
  • 0 ≤ an element in S ≤ 109
  • 0 ≤ an element in T ≤ 109
  • Sample Input 1
  • 5
    1 2 3 4 5
    3
    3 4 1

    Sample Output 1

    3

    Sample Input 2

    3
    1 2 3
    1
    5

    Sample Output 2

    0

    Sample Input 3

    5
    1 1 2 2 3
    2
    1 2

    Sample Output 3

    2

二分算法:

#include<stdio.h>
#include<iostream>
using namespace std;
#include<string>
#include<string.h>
#include<algorithm>
#include<queue>
#include<vector>
#include<list>
#include<set>
const int maxn=100005;
typedef long long ll;
bool erfen(ll *a,ll left,ll right,ll num)
{
	while(left<right)
	{
	ll mid=(left+right)/2;
	if(num==a[mid])
		return true;
	else if(num<a[mid])
		right=mid;
	else if(num>a[mid])
		left=mid+1;
	}
	
	return false;
}
int main()
{
	ll num;
	ll a[maxn];
	ll i;
	ll n;
	ll k=0;
	cin>>n;
	for(i=0;i<n;i++)
		cin>>a[i];
	sort(a,a+n);
	ll q;
	cin>>q;
	for(i=0;i<q;i++)
		{
			cin>>num;
			if(erfen(a,0,n,num))
				k++;
		}
	cout<<k<<endl;
	return 0;
}

用到STL 问题就相对于简单一点(其实一样)

下面看一个用一个 lower_bound 来实现:

代码:

#include<stdio.h>
#include<iostream>
using namespace std;
#include<string>
#include<string.h>
#include<algorithm>
#include<queue>
#include<vector>
#include<list>
#include<set>
const int maxn=100005;
typedef long long ll;
int main()
{
	ll k=0;
	ll i;
	ll a[maxn];
	ll n,q;
	cin>>n;
	for(i=0;i<n;i++)
		cin>>a[i];
	cin>>q;
	for(i=0;i<q;i++)
		{
			ll num;
			cin>>num;
			ll pos=lower_bound(a,a+n,num)-a;
			if(a[pos]==num)
				k++;
		}
	cout<<k<<endl;
	return 0;
}

 下面就用一个 set 就可以实现,代码:

#include<stdio.h>
#include<iostream>
using namespace std;
#include<string>
#include<string.h>
#include<algorithm>
#include<queue>
#include<vector>
#include<list>
#include<set>
const int maxn=2000005;
typedef long long ll;
int main()
{
	ll k=0;
	ll num;
	int i;
	set<ll>s1;
	set<ll>s2;
	set<ll>::iterator it=s2.begin();
	int n,q;
	cin>>n;
	for(i=0;i<n;i++)
		{
			cin>>num;
			s1.insert(num);
		}
		cin>>q;
	for(i=0;i<q;i++)
		{
			cin>>num;
			s2.insert(num);
		}
	for(it=s2.begin();it!=s2.end();it++)
		{
			if(s1.find(*it)!=s1.end())
				k++;
		}
	cout<<k<<endl;
	return 0;
}

简单说的说一下原理吧,先将 是数组排序(必要条件)否则二分不能实现,就是每次将区间分一半,在左边的话,就抛弃右边;在右边,就抛弃左边。大大的减少了时间。、

3.有的搜索就可以直接用STL实现,(比如一些set vector 有一些搜索的函数 find()  ),就可以直接套用。

看看题:

您的任务是编写一个简单字典程序,该程序实现以下指令:              

您的任务是编写一个简单字典程序,该程序实现以下指令:              

insert str:在字典中插入字符串str              

查找str:如果distinary包含str,则打印“yes”,否则打印“no”              

输入              

在第一行n中,给出了指令数。在以下n行中,n条指令以上述格式给出。              

产量              

对一行中的每个查找指令打印“是”或“否”。              

约束条件              

字符串由“a”、“c”、“g”或“t”组成              

1≤字符串长度≤12              

n=1000000 

代码:

#include<stdio.h>
#include<iostream>
using namespace std;
#include<string>
#include<string.h>
#include<algorithm>
#include<queue>
#include<vector>
#include<list>
#include<set>
const int maxn=100005;
typedef long long ll;
int main()
{
	char zifu[20];
	char zhiling[20];
	ll t;
	cin>>t;
	set<string>s;
	while(t--)
	{
		cin>>zhiling>>zifu;
		if(zhiling[0]=='i')
			{
				s.insert(zifu);
			}
		else if(zhiling[0]=='f')
			{
				if(s.find(zifu)!=s.end())
					cout<<"yes"<<endl;
				else 
					cout<<"no"<<endl;	
			}	
	}
	return 0;
}

这些 stl 的用法,应该要掌握,不了解的,可以看看博客学习一下。

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值