二分法的变种

二分法查找使用的前提是一串数据必须是有序的(递增或递减),时间复杂度是O(lgN),查找速度特别快;

但是对于这样一串数据4 5 6 1 2 3,前一部分是递增,后一部分也是递增,这样一串数据怎么去使用二分法查找呢?

把一个数组最开始的若干个元素搬到数组的末尾,称之为数组的旋转。上面的 4 5 6 1 2 3就是数组 1 2 3 4 5 6的一个旋转。看看这样一道题:输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。

 测试用例:

功能测试(数组中有重复数字或者没有重复数字)

边界值测试(输入数组是一个升序排序的数组,只包含一个数字的数组)

特殊输入测试(输入NULL指针)

分析:

数组为空;

只有一个数字的数组;

正常数组(旋转前递增,无重复,数字个数大于一个);

有重复数字的数组;

一定要考虑数组中有相同数字的特例;4 5 6 1 2 3, 1 1 1 0 1 1。

开始解题:

我们先处理正常情况下的


处理有重复数字的:

0 1 1 1 1 1旋转之后的结果1 1 1 0 1 1

对于这样的我们无法知道mid是位于第一个区间还是第二个区间,只能去一个个遍历查找最小值;

int MinOrder(int arr[], int start, int end)    //顺序查找最小值,处理有重复数字的情况
{
	int result = arr[start];
	while (start <= end)
	{
		if (arr[start] < result)
		{
			result = arr[start];
		}

		start++;
	}

	return result;
}

int MinBinary(int arr[], int length)
{
	if (arr == NULL || length <= 0)
	{
		cout << "数组错误" << endl;
		return -1;
	}

	int start = 0;
	int end = length - 1;
	int mid = 0;

	if (length == 1)   //只有一个元素
	{
		return arr[0];
	}

	

	while ((start + 1) != end)
	{
		mid = (start&end) + (start^end) >> 1;

		if (arr[start] == arr[end] && arr[start] == arr[mid])
			return MinOrder(arr, start, end);

		if (arr[mid] >= arr[start])
		{
			start = mid;
		}
		else if (arr[mid] <= arr[end])
		{
			end = mid;
		}
	}
	return arr[end];
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值