剑指offer--------旋转数组的最小数字

本文介绍了一种在旋转数组中查找最小元素的有效方法。通过顺序查找和改进的二分查找算法,文章详细解释了如何处理特殊情况,并给出了具体的C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

思路1:顺序查找,时间复杂度o(n);

实现:

int GetMin(vector<int>& numbers)
{
	int len = numbers.size();
	if (len < 0)
	{
		throw exception("input invalid!");
	}
	int res = numbers[0];
	for (int i = 1; i < len; i++)
	{
		if (res > numbers[i])
		{
			res = numbers[i];
		}
	}
	return res;
}

思路2:根据旋转数组的规则:

一般情况,第一个元素大于等于最后一个元素,采用二分查找有:

(1)设置两个指针P1和P2分别指向数组的第一个和最后一个元素;

(2)找到数组的中间元素,若中间元素大于等于第一个元素,则最小元素位于中间元素的后面;

(3)若中间元素小于等于最后一个元素,则最小元素位于中间元素的前面;

(4)重复上述过程,则第一个指针总是指向前面递增数组的元素,第二个指针总是指向后面递增数组的元素,当P1和P2指向两个相邻的元素时,P2指向的就是最小元素。

实现

int GetMin(vector<int>& numbers)
{
	int index1 = 0;
	int index2 = numbers.size() - 1;
	int minIndex;  
	while (numbers[index1] >= numbers[index2])
	{
		if (index2 - index1 == 1)
		{
			minIndex = index2;
			break;
		}
		minIndex = index1 + (index2 - index1) / 2;
		if (numbers[minIndex] >= numbers[index1])index1 = minIndex;
		if (numbers[minIndex] <= numbers[index2])index2 = minIndex;
	}
	return numbers[minIndex];
}

在思路2中有两种特殊情况,分别是:

(1)原数组可看成将前0个元素搬到数组末尾的旋转数组,则第一个元素小于等于最后一个元素,此时,最小元素就为第一个元素,因此解决方案为初始化中间元素下标为第一个元素下标。

(2)在一般情况中,当第一个元素、中间元素、最后一个元素三者相等时,认为最小元素位于中间元素的后面。但实际情况并非如此。比如:数组{1,0,1,1,1}是数组{0,1,1,1,1}的旋转,此时,第一个元素、中间元素、最后一个元素的值都为1,但最小元素位于中间元素的前面;当出现这种情况时,采用顺序查找确定最小元素。

实现

int GetMin(vector<int>& numbers)
{
	int index1 = 0;
	int index2 = numbers.size() - 1;
	int minIndex = index1;         //特例1的解决方案。
	while (numbers[index1] >= numbers[index2])
	{
		if (index2 - index1 == 1)
		{
			minIndex = index2;
			break;
		}
		minIndex = index1 + (index2 - index1) / 2;
		if (numbers[index1] == numbers[index2] && numbers[index1] == numbers[minIndex])        //特例2的解决方案
		{
			return minInorder(numbers, index1, index2);
		}
		if (numbers[minIndex] >= numbers[index1])index1 = minIndex;
		if (numbers[minIndex] <= numbers[index2])index2 = minIndex;
	}
	return numbers[minIndex];
}
int minInorder(vector<int>& numbers, int index1, int index2)
{
	int res = numbers[index1];
	for (int i = index1 + 1; i <= index2; i++)
	{
		if (res > numbers[i])
		{
			res = numbers[i];
		}
	}
	return res;
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值