面试OR笔试40——二分查找一个函数解决多个问题

61 篇文章 0 订阅
61 篇文章 0 订阅

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;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值