输入样例:
9 6
1 1 2 2 3 4 5 5 5
1 2 3 4 5 6
结尾无空行
输出样例:
0 2 4 5 6 -1
结尾无空行
一开始以为自己已经掌握了二分,实际上还没入门WAWAWAWA!!
仔细一看这是一道查找下标的题
之前做的二分查找都是给定不重复是数,现在是包含重复的数
这里就需要考虑两种特殊情况
1.a[mid]是目标数,但是前面一位也是
2.第一位是目标数 二分搜索不到
最后一位是目标数但是末尾有连续目标数 二分查找第一个下标会找到错误下标
注意:一个小细节二分查找一般数据很大中间下标用
mid = love + (life - love) / 2;//防止溢出
表示 防止溢出
变量解释 :
love 查找区间左端
life 查找区间右端
查找一个数是否存在代码
#include <iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstdio>
using namespace std;
int main()
{
int a[10000];
long n, m;
int temp;
printf("请输入数组元素数:\n");
scanf("%ld", &n);
long i, j, k;
printf("请输入数组元素:\n");
for (i = 0; i < n; i++)
{
scanf("%d", &a[i]);
}
sort(a, a + n);
int love = 0;
int life = n - 1;
int mid = love + (life - love) / 2;//防止溢出
int findit;
printf("请输入查找数字:\n");
scanf("%d", &findit);
int f=0;
while (love <= life)
{
if (findit == a[mid])
{
f=1;
break;
}
else if (findit < a[mid])
life = mid - 1;
else
love = mid + 1;
mid = love + (life - love) / 2;
}
if (f)
{
printf("排序后其下标:%d ", mid);
}
else
{
printf("-1 \n没有找到");
}
return 0;
}
查找数第一次出现下标代码
(为了易于阅读这里取消了格式控制)
坑点都在debug日志里面了
#1 #2 对应解决办法
#include <iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstdio>
using namespace std;
int a[1000101];
int main()
{
/*
*debug 日志 #1. 没有取等 中间考虑不到
* #2. 1 2连续 第一个考虑不到 最后一个考虑不到
*
*
*/
long n,m;
int temp;
scanf("%ld %ld",&n,&m);
long i,j,k;
for( i=0; i<n; i++)
{
scanf("%d",&a[i]);
}
sort(a,a+n);
while(m--)
{
int findit;
scanf("%d",&findit);
int love=0,life=n-1;
int mid=love+(life-love)/2;
int f=0;//找到标记 默认未找到
if(findit==a[0]) //#2
{
printf("0 ");
continue;
}
if(findit==a[n-1])//看看前面有没有 //#2
{
int temp=n-1;
while(a[temp]==a[temp-1])
temp--;
printf("%d ",temp);
continue;
}
while(love<=life) // #1
{ //没有加等于号 就会在love==life时找不到那个数
if(a[mid]<findit)
love=mid+1;
else if(a[mid]>findit)
life=mid-1;
else//有缺陷 找不到前面一个 判断一手
{
while(a[mid]==a[mid-1])
{
mid--;
}
printf("%d ",mid);
f=1;
break;
}
mid=love+(life-love)/2;
}
if(!f)
printf("-1 ");
}
printf("\n");
return 0;
}
ok!