二分 - 整数

一、概述

整数二分常用于解决寻找某些性质的边界的问题,性质往往是整数大小的范围

例如使用整数二分寻找下图所示的分界点1 和 分界点2:

整数二分大致分为三个步骤 :

1、由l==0r==n-1确定区间中间点mid

注意!midmid=l+r>>1 和 mid=l+r+1>>1两种确定方式

2、检查mid处的性质;

3、根据步骤2的结果相应地调整区间

例如寻找分界点1:

mid处的性质为红色,则分界点1必定位于区间[mid,r]中,所以l=mid

mid处的性质为绿色,则分界点1必定位于区间[l,mid-1]中,所以r=mid-1

例如寻找分界点2:

mid处的性质为绿色,则分界点2必定位于区间[l,mid]中,所以r=mid

mid处的性质为红色,则分界点2必定位于区间[mid+1,r]中,所以l=mid+1

二、题目

数的范围

三、代码段

#include<iostream>
using namespace std;

const int N = 1e5+10;

int n,q,k;//长度为n、q次查询、查询k
int A[N];

int main()
{
    cin>>n>>q;
    
    for(int i=0;i<n;i++)
      cin>>A[i];
      
    while(q--)
      {
          cin>>k;
          
          //核心代码块(1)
          int l=0,r=n-1;
          while(l<r)
            {
                int mid=l+r>>1;//步骤1、确定区间中间点mid
                if(A[mid]>=k)  //步骤2、检查mid处的性质
                  r=mid;       //步骤3、根据步骤2的结果相应地调整区间
                else           
                  l=mid+1;
            }
            
          if(A[l]!=k)  cout<<"-1 -1"<<endl;
          //如果数组中不存在该元素,则返回 -1 -1
          
          else
            {
                cout<<l<<" ";
                
                //核心代码块(2)
                l=0; r=n-1;
                while(l<r)
                  {
                      int mid=l+r+1>>1;//步骤1、确定区间中间点mid
                      if(A[mid]<=k)    //步骤2、检查mid处的性质
                        l=mid;         //步骤3、根据步骤2的结果相应地调整区间
                      else           
                        r=mid-1;
                  }
                  
                cout<<l<<endl;
            }
      }
      
    return 0;
}
#include<iostream>
using namespace std;

const int N = 1e5+10;

int n,q,k;
int A[N];

int main()
{
    cin>>n>>q;
    
    for(int i=0;i<n;i++)
      cin>>A[i];
      
    while(q--)
      {
          cin>>k;
          
          int l=0,r=n-1;
          while(l<r)
            {
                int mid=l+r>>1;
                if(A[mid]>=k)  r=mid;
                else           l=mid+1;
            }
            
          if(A[l]!=k)  cout<<"-1 -1"<<endl;
          
          else
            {
                cout<<l<<" ";
                
                l=0; r=n-1;
                while(l<r)
                  {
                      int mid=l+r+1>>1;
                      if(A[mid]<=k)  l=mid;
                      else           r=mid-1;
                  }
                  
                cout<<l<<endl;
            }
      }
      
    return 0;
}
//提取核心代码块



//核心代码块(1)
int l=0,r=n-1;
while(l<r)
  {
      int mid=l+r>>1;
      if(A[mid]>=k)  r=mid;       
      else           l=mid+1;
  }
  
//若r=mid,则l=mid+1 且 mid=l+r>>1

//对于至少包含一个整数且按照升序排列的整数数组A执行完核心代码块(1)后:
//1、l==r;
//2、若A中包含大于或等于k的元素,则A[l]==A[r]为A中第一个大于或等于k的元素;
//3、若A中只包含小于k的元素,则A[l]==A[r]==A[n-1]为A中最后一个元素
 
 
            
//核心代码块(2)
l=0; r=n-1;
while(l<r)
  {
      int mid=l+r+1>>1;
      if(A[mid]<=k)  l=mid;         
      else           r=mid-1;
  }
  
//若l=mid,则r=mid-1 且 mid=l+r+1>>1

//对于至少包含一个整数且按照升序排列的整数数组A执行完核心代码块(2)后:
//1、l==r;
//2、若A中包含小于或等于k的元素,则A[l]==A[r]为A中最后一个小于或等于k的元素;
//3、若A中只包含大于k的元素,则A[l]==A[r]==A[0]为A中第一个元素

推荐文章: 二分查找 - 整数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值