二分法和STL

为什么二分

假设每次取的是最左边的一个k等分点,那么在检测之后区间大小可能变成原来的1/k或者1-1/k,假设在查找范围中的数的分布是绝对均匀的,那么区间变成1/k的概率是1/k.同样,变成1-1/k的概率为1-1/k,那么检测之后期望的区间长度为:
r a n g e ∗ ( 2 / k 2 − 2 k + 1 ) range*(2/k^2-\frac{2}{k}+1) range(2/k2k2+1)
这是个二次函数 ,当k=2时,取最小值

代码

前提:数组有序
这里假设为非递减数组

low=1;
high=n;
while(low<=high)
{
	mid=(low+high)/2;
	if(a[mid]==x)
	{
		return mid;
	}
	else if(a[mid]<=x)
	{
		low=mid+1;
	}
	else
	{
		high=mid-1;
	}
}
//在实数域上二分,eps为精度值,将循环条件改为
while(r-l>=eps)

二分和STL

STL中的一些二分应用

a[9]
//在非递减数列中找到第一个大于或等于3的数的坐标(upper_bound是返回第一个大于的数)
//这个函数返回的是地址,故需要减去起始地址,获得下标
//不存在会返回end
int index=lower_bound(a,a+9,3)-a

//通过重载使其应用在从大到小的数列中,找到第一个小于(小于等于)的数的位置
upper_bound( begin,end,num,greater<type>() )//这里的type自己填

数组地址相减

上边的代码中有涉及到数组地址的相减直接得到下标。
实际上,执行完数组地址相减运算后,还会执行算数右移指令,右移位数视参数类型而定,如int型右移2位,short型右移1位。
即两个数组元素地址相减,实际是获取两个元素数组元素的距离,而不是地址的距离。

vector和set中的upper_bound()

//vector中
auto it =upper_bound( a.begin(),a.()end,3);
//set中
it=upper_bound(s.begin(),s.end(),x);
it=s.upper_bound(x); //如果是查找整个集合中可以这样写

stl复杂度

这里补充下STL中各种容器的复杂度

vector

头部插入删除:O(N)
尾部插入删除:O(1)
中间插入删除:O(N)
查找:O(N)

双向队列

头部尾部插入删除:O(1)
中间插入删除:O(N)
查找:O(N)

list

插入删除:O(1)
头尾查询:O(1)
其他位置查询:O(N)

set、map

增删改查近似:O(log N)

题目

解方程

在这里插入图片描述
看题,应该是要枚举的,但是不用三个都枚举,可以枚举a,b然后二分法找有没有合适的C,从而降低复杂度

代码

#include<bits/stdc++.h>
using namespace std;

//枚举两个二分找-c
bool find(int c,int*a,int n)
{
    int index;
    index=lower_bound(a,a+n,c)-a;
    if(a[index]==c)
        return true;
    return false;
}
int main()
{
    int n,x;
    int a0,b,c;
    cin>>n>>x;
    int *a=new int[n];
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
    }
    sort(a,a+n);
    for(int i=0;i<n;i++)
    {
        a0=a[i];
        for(int j=0;j<n;j++)
        {
            b=a[j];
            c=(-1)*(a0*pow(x,2)+b*x);
            if(find(c,a,n))
            {
                cout<<"YES";
                return 0;
            }

        }
    }
    cout<<"NO";
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值