二分(两段性)
起因
2023蓝桥杯B组金属冶炼,想到用二分但不知道怎么写,确切地说是忘了板子的具体细节
板子
用哪个板子都可以写出来二分题,但是具体实现细节需要看题目的要求
左闭右闭
1. l=0,r=ArraySize-1
2. l<=r
3. l=mid+1; r=mid-1;
4. mid = l + (l - r)/2 或 mid = (l + r)/2
#include<bits/stdc++.h>
using namespace std;
const int N=1e5;
int a[N];
signed main(){
int n;
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
int l=0,r=n-1;
int mid;
while(l<=r){
mid=(l+r)>>1;
if(a[mid]>a[0]) l=mid+1;
else r=mid-1;
}
cout<<a[mid]<<endl;
return 0;
}
左闭右开
1. l=0,r=ArraySize
2. l<r
3. l=mid+1; r=mid;
4. mid = (l + r)/2
#include<bits/stdc++.h>
using namespace std;
const int N=1e5;
int a[N];
signed main(){
int n;
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
int l=0,r=n;
int mid;
while(l<r){
mid=(l+r+1)>>1;
if(a[mid]>a[0]) l=mid+1;
else r=mid;
}
cout<<a[mid]<<endl;
return 0;
}
左开右闭
1. l=-1,r=ArraySize-1
2. l<r
3. l=mid; r=mid-1;
4. mid = l + (l - r)/2
#include<bits/stdc++.h>
using namespace std;
const int N=1e5;
int a[N];
signed main(){
int n;
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
int l=-1,r=n-1;
int mid;
while(l<r){
mid=(l+r+1)>>1;
if(a[mid]>a[0]) l=mid;
else r=mid-1;
}
cout<<a[mid]<<endl;
return 0;
}
例题
- 旋转数组
- 金属冶炼
旋转数组
题面
题解
int minNumberInRotateArray(int* rotateArray, int rotateArrayLen ) {
// write code here
int left = 0;
// 如果是 right = rotateArrayLen;
// (rotateArray + right) 会越界
int right = rotateArrayLen-1;
int mid = 0;
while (left < right)
{
mid = (left + right) / 2;
if (*(rotateArray + right) > *(rotateArray + mid))
{
right = mid;
}
else if (*(rotateArray + right) == *(rotateArray + mid))
{
right--;
}
else
{
left = mid + 1;
}
}
return rotateArray[left];
}