一.三种二分查找函数(下面使用时都必须排序)
头文件:
#include<algorithm>
1.binary_search()
(1)功能:查找某个元素是否出现,其返回值是bool,若找到这个元素返回真,否则返回假。
(2)模板:
数组中:binary_search(num,num+n,k)//在num数组中找元素k
vector中:binary_search(num.begin(),num.end(),k)//在num容器里找k
set中:binary_search(num.begin(),num.end(),k)//在num容器里找k,但是set中count和find函数提供了查找功能
2.lower_bound()
(1)功能:返回 第一个 大于等于元素的位置(该位置是指针或者迭代器),如果所有元素都小于k,则返回最后一个位置last,注意最后一个last是越界的!
(2)模板:
<1>数组:lower_bound(num,num+n,k)//在数组num里查找大于等于k的位置(从0开始)
int pos=lower_bound(num,num+n,k)-num;(指针相减即为位置坐标,若没有则pos==n)
<2>vector:lower_bound(num.begin(),num.end(),k)
int pos=lower_bound(num.begin(),num.end(),k)-num.begin();//迭代器相减即为坐标位置
3.upper_bound()
(1)功能:返回第一个 大于 元素k的位置,若没有返回last同 上。
模板功能同上不再赘述
详情点击:点击打开链接
例题:HDU2141 Can you find it?
传送门:点击打开链接
题意:给三个数组a,b,c和数字X,问能否找到a+b+c=X
思路:枚举ab,二分查找X-a-b在c中有没有;或者创建a+b新数组,枚举c,判断X-c在(a+b)数组里有没有出现。
代码:
#include <iostream> #include<cstdio> #include<map> #include<cstring> #include<algorithm> using namespace std; long long int numA[505]; long long int numB[505]; long long int numC[505]; long long int all[1000000]; int main() { int l,n,m; int t=0; while(scanf("%d%d%d",&l,&n,&m)!=EOF) { t++; int i; for(i=0; i<l; i++) { scanf("%lld",&numA[i]); } int j; for(j=0; j<n; j++) { scanf("%lld",&numB[j]); } int k; for(k=0; k<m; k++) { scanf("%lld",&numC[k]); } int s; scanf("%d",&s); printf("Case %d:\n",t); int len=0; for(int p=0;p<i;p++) { for(int q=0;q<j;q++) { all[len++]=numA[p]+numB[q]; } } sort(all,all+len); sort(numC,numC+k); int len2=unique(all,all+len)-all; int k2=unique(numC,numC+k)-numC; while(s--) { long long int X; bool judge=false; scanf("%lld",&X); for(int m=0;m<k2;m++) { long long int ans=X-numC[m]; if(binary_search(all,all+len2,ans)) { judge=true; break; } } if(judge) puts("YES"); else puts("NO"); } } return 0; }
二.求集合函数
见文章:点击打开链接
三.全排列函数
头文件:
#include<algorithm>
(1)概念:“下一个排列组合”和“上一个排列组合”,对序列 {a, b, c},每一个元素都比后面的小,按照字典序列,固定a之后,a比bc都小,c比b大,它的下一个序列即为{a, c, b},而{a, c, b}的上一个序列即为{a, b, c},同理可以推出所有的六个序列为:{a, b, c}、{a, c, b}、{b, a, c}、{b, c, a}、{c, a, b}、{c, b, a},其中{a, b, c}没有上一个元素,{c, b, a}没有下一个元素。
(2)函数功能: 返回值为bool类型,当当前序列不存在下一个排列或者上一个排列时,函数返回false,否则返回true,排列好的数在容器中存储,
(3)模板:(全排列函数是会更改容器内容的!)
〈1〉next_permutation:求下一个排列组合
数组:next_permutation(arr, arr+size);
vector:next_permutation(arr.begin(), arr.end());
注意:在使用前需要对欲排列数组按 *升序* 排序,否则只能找出该序列之后的全排列数。
比如,如果数组num初始化为2,3,1,那么输出就变为了:{2 3 1} {3 1 2} {3 2 1}
<2>prev_permutation:求上一个排列组合
数组:next_permutation(arr, arr+size);
vector:next_permutation(arr.begin(), arr.end());
注意:在使用前需要对欲排列数组按降序排序,否则只能找出该序列之后的全排列数。
(4)常用算法模板
do { for(int i=0;i<5;i++) cout<<num2[i]<<" "; cout<<endl; }while(next_permutation(num3.begin(),num3.end()));
(5)例题
Poj2718 Smallest Difference
传送门:点击打开
题意:给出最多10个数字,将它们划分为两个整数,求差值最小的值(除非只有一位数,否则不允许出现先导0)
思路:很显然如果总共有n个数,必然有一个整数长n/2,另一个长n-n/2,暴力枚举全排列,求最小差值!
代码:
#include <iostream> #include<algorithm> #include<cmath> #include<cstdio> using namespace std; #define INF 0x3f3f3f3f int num[15]; int main() { int T; cin>>T; getchar(); while(T--) { int a; int len=0; string s; getline(cin,s); for(int i=0; i<s.size(); i++)//输入题目没说eof就是以换行结束!只能字符串!! { if(s[i]>='0'&&s[i]<='9') num[len++]=s[i]-'0'; } if(len==2) cout<<num[1]-num[0]<<endl; else { int minn=INF; do { int mid=len/2; if(!num[0]||!num[mid]) continue; int sum1=0,sum2=0; for(int i=0; i<mid; i++) { sum1*=10; sum1+=num[i]; } for(int i=mid; i<len; i++) { sum2*=10; sum2+=num[i]; } minn=min(minn,abs(sum1-sum2)); } while(next_permutation(num,num+len)); cout<<minn<<endl; } } return 0; }
四:去重函数
(1) unique()是C++标准库函数里面的函数,其功能是去除相邻的重复元素(只保留一个),所以使用前需要对数组进行排序!!它会把重复的元素添加到容器末尾(所以数组大小并没有改变),而返回值是去重之后的尾地址.
(2)模板
数组:
sort(num,num+12); int len=unique(num,num+12)-num;//去重后的长度vector:
sort(num2.begin(),num2.end()); int len=unique(num2.begin(),num2.end())-num2.begin();