面试题11:旋转数组的最小数字

面试题11:旋转数组的最小数字

题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转旋转数组的最小元素。例如数组{3,4,5,1,2}是数组{1,2,3,4,5}的一个旋转,该数组的最小值为1。

思路:

  • 方法一:通过顺序查找法可以在O(n)的时间里找到最小的数字。根据该数组的特点,肯定不是最优解;

  • 方法二:通过二分查找法查找。和一般的有序数组不一样,该数组通过旋转操作将该数组分为了两个子数组,而且两个子数组都是有序的。根据该特点,我们可以给前后两个子数组分配一个指针。查找过程:
    1 .第一个指针p1指向第一个元素,第二个指针p2指向最后一个元素;
    2 .求两指针的中间位置,若中间位置到值大于第一个指针所指,则说明中间位置在第一个子数组中,则更新第一个指针;若中间位置到值小于第二个指针所指,则说明中间位置在第二个子数组中,则更新第二个指针
    3 .更新完指针后,若两指针相邻,则返回第二个指针所指的值,否者进行2步。

    特殊情况:第2步中,若第一个指针和第二个指针以及中间的值相等,则不能再用二分查找,改为顺序查找

代码:

#include <iostream>

using namespace std;

int minInRotateArr(int rotateArr[], int length);

int main() {

	int rotateArr[] = { 4,5,6,7,8,2,2,3 };
	int min = minInRotateArr(rotateArr, 8);
	cout << "min:" << min << endl;
	return 0;
}


int minInRotateArr(int rotateArr[], int length) {

	if (rotateArr == nullptr || length <= 0) {
		return -1;
	}

	int p1 = 0;//指向前一个子数列的指针
	int p2 = length - 1;//指向后一个子数列的指针
	int mid = p1;
	while (rotateArr[p1] >= rotateArr[p2]) {

		//结束条件:前一个子数列的指针和后一个子数列指针相邻,那么最小的值就位于后一个指针所指出
		if (p2 - p1 == 1) {
			return rotateArr[p2];
		}

		mid = (p1 + p2) / 2;
		//如果中间的值和两端一样,只能顺序查找
		if (rotateArr[p1] == rotateArr[p2] && rotateArr[p1] == rotateArr[mid]) {
			int min = rotateArr[p1];
			for (int i = p1 + 1; i <= p2; i++) {
				if (min > rotateArr[i]) min = rotateArr[i];
			}
			return min;
		}
		//如果中间的值比前一个指针指向的值大,说明mid所处前一个子数列
		if (rotateArr[mid] >= rotateArr[p1]) {
			p1 = mid;
		}
		//如果中间的值比后一个指针指向的值小,说明mid所处前一个子数列
		else if (rotateArr[mid] <= rotateArr[p2]) {
			p2 = mid;
		}
	}

	return rotateArr[mid];
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值