面试OR笔试40——二分查找一个函数解决多个问题
来源:互联网 发布:意尔康程序员面试题 编辑:程序博客网 时间:2024/06/07 06:34
1 题目及要求
1.1 题目描述
二分查找相关问题一直是面试中的热门问题之一。有序数组的二分查找问题大致就分为那么8类(参考,作者:LightGHLi连接:https://www.zhihu.com/question/36132386/answer/105595067):
(1)对于不下降序列a,求最小的i,使得a[i]= key;
(2)对于不下降序列a,求最大的i,使得a[i]= key;
(3)对于不下降序列a,求最小的i,使得a[i]> key;
(4)对于不下降序列a,求最大的i,使得a[i]< key;
(5)对于不上升序列a,求最小的i,使得a[i]= key;
(6)对于不上升序列a,求最大的i,使得a[i]= key;
(7)对于不上升序列a,求最小的i,使得a[i]< key;
(8)对于不上升序列a,求最大的i,使得a[i]> key。
而如果对于每个不同的类型都去具体实现,则会涉及二分向上或者向下取整,区间的开闭,以及判断条件的改变等。情况太多,记起来特别麻烦还特容易混淆。
下面针对不下降序列,只用一个二分查找去实现(1)到(4)的不同功能。其中当存在i时则返回i,否则返回-1。
首先实现一个 intbinarySearch(int *v, int vn, int k)的函数,v为输入数组(不下降序列),n为其长度,k为待查找数值。该函数的功能为返回最小i,使得k<=v[i](也即k<=v[i] 且 v[i-1]<k);当输入为空时返回-1。注意该函数有坑能返回数组的长度,也即尾后下标。
下面利用该函数实现(1)到(4)
(1) int bs1(int*v, int vn, int k)
调用 index = binarySearch(v,vn,k),则有v[index-1]<k <=v[index]。因此当v[index]==k时,index就是所求;否则不存在。
(2) intbs2(int *v, int vn, int k)
调用 index = binarySearch(v,vn,k+1)-1,则有k+1 <=v[index+1]且 v[index] < k+1,
也即k < v[index+1] 且 v[index]<=k。因此当v[index]==k时,index就是所求;否则不存在。
(3) intbs3(int *v, int vn, int k)
调用 index = binarySearch(v,vn,k+1),则有k+1 <=v[index]且 v[index-1] < k+1,
也即v[index-1]<= k < v[index]。index即为所求。(返回尾后下标时特别处理)。
(4)int bs4(int*v, int vn, int k)
调用 index = binarySearch(v,vn,k)-1,则有k <=v[index+1]且 v[index] < k,
也即v[index]< k <= v[index+1]。index即为所求。index即为所求。
2 解答
2.1 代码
#include <iostream>#include <string>#include <iomanip>using namespace std;int binarySearch(int *v, int vn, int k) {if (!v || vn < 1) return -1;int lo(0), up(vn), mid;while (lo < up) {mid = lo + ((up - lo) >> 1);if (v[mid] < k) lo = mid + 1;else up = mid;}return lo;}int bs1(int *v, int vn, int k) {if (!v || vn < 1) return -1;int index = binarySearch(v, vn, k);return v[index] == k ? index : -1;}int bs2(int *v, int vn, int k) {if (!v || vn < 1) return -1;int index = binarySearch(v, vn, k + 1) - 1;return v[index] == k ? index : -1;}int bs3(int *v, int vn, int k) {if (!v || vn < 1) return -1;int index = binarySearch(v, vn, k + 1);return index == vn ? -1 : index;}int bs4(int *v, int vn, int k) {if (!v || vn < 1) return -1;return binarySearch(v, vn, k) - 1;}int main() {int a[] = { 1,2,2,2,4,4,5 }, n = sizeof(a) / sizeof(a[0]);cout << "输入数组:";for (int k1(0);k1 < n;++k1) cout << setw(8) << a[k1] << ' ';cout << endl << "数组下标:";for (int k1(0);k1 < n;++k1) cout << setw(8) << k1 << ' ';cout << endl << "查找数值" << " bs1 bs2 bs3 bs4" << endl;for (int k1(1);k1 < n+1;++k1) {cout << setw(8) << k1 << setw(8) << bs1(a, n, k1)<< setw(8) << bs2(a, n, k1) << setw(8) << bs3(a, n, k1)<< setw(8) << bs4(a, n, k1) << endl;}return 0;}