二分法 多适用于有序数列,查找某一数值的位置,举个问题:若序列中数字相同,输出最小编号的位置。
int a[1000010]; //开一个数组
int main() {
int n, m;
scanf("%d %d", &n, &m); //n为单调递增序列数的个数 m为需要查找数的数目
for (int i = 0; i < n; i++) {
scanf("%d", &a[i]); //读入递增数列 可能为0,1,1,2,3,3
}
for (int i = 0; i < m; i++) {
int left = 0; int right = n-1;
int k;
scanf("%d", &k); //需要查找的数
while (left <= right) {
int t = (left + right) / 2;
if (k<=a[t] ) right = t - 1;
else left= t + 1;
}
if (a[left] == k) printf("%d ", left + 1);
else printf("-1 ");
}
return 0;
}
①由于要找编号最小,所以需要k=a[t]时,让right=t-1;这样继续循环,如果左边还有k这个数,在之后循环中right会继续左移.
②同时由于while(left<=right) 且k>a[t]时left=t+1,最终结束循环时 left一定是=right+1;又由于 如果结束前找到了k(t位置),那么right=t-1(left位置为right+1=t);所以最终输出的是left的位置 。
③综合①和②就可以找出最小编号的位置
以上为对找有序数列最小编号的思考,如果是找最大编号那么代码改为 :
while (left <= right) {
int t = (left + right) / 2;
if (k>=a[t] ) left = t + 1;
else right= t - 1;
}
if (a[right] == k) printf("%d ", right +1);
else printf("-1 ");
正好和上述情况相反