求旋转数组的最小数字C++

发现还是数组这种最简单的编码才适合我,遇到树,链表这些真的是一头雾水,自己也不知道怎么实现。言归正传,该篇文章介绍如何求旋转数组的最小值,求最大值可以适当改编即可。

什么是旋转数组呢,就是将一个数组的前几个元素和后面几个元素互换位置。例如原数组(升序的数组)为{0,1,2,3,4,5,6,7,8,9},将其旋转后变为{5,6,7,8,9,0,1,2,3,4}。如何求该数组的最小值呢,有一种方法是直接按顺序比较,但是这就体现不出旋转数组的特性了,所以更好的解法应该是采用二分法来求得该数组的最小值。我们可以发现在旋转数组中9坐标的数都比它小,右边的数也都比它小。我们设有2个指针,左指针指向最左边的元素,右指针指向最右边的元素。我们判断中间的元素和最左边元素的大小,如果中间的数大于左指针指向的元素,证明最小的数字在中间数字的右边。这样我们就可以缩小范围啦。

代码如下

#include<iostream>
#include<cstdlib>
#include <stack>
#include <stdio.h>
#include<time.h>

using namespace std;

int Min(int a[], int length)
{
	if (a == nullptr || length <= 1)       //如果出现数组中只有一个元素的就直接报错吧
		throw new exception("Invalid parameters");

	int left = 0;
	int right = length - 1;
	while (a[left] > a[right])           
	{
		if (right <= left+2)             //数组中有2个或者三个元素,最右边的元素都是最小的
			return a[right];

		int mid = (left + right) / 2;
		if (a[mid] >= a[left])
			left = mid;
		else if (a[mid] < a[right])
			right = mid;

	}
	return a[right];
}

int main()
{
	int a[] = { 44,45,46,1,2,3,15,33,41 };
	int min=Min(a, 6);
	cout << min << endl;
	system("pause");

}

不过很显然这种方法不是很完善的,因为没有考虑一种比较特殊的情况,就是数组中拥有重复元素的时候。比如数组{1,1,1,0,1},{1,0,1,1,1}。这种时候就只能选择顺序查找的办法啦。

改进代码如下:

#include<iostream>
#include<cstdlib>
#include <stack>
#include <stdio.h>
#include<time.h>

using namespace std;

int MinInOder(int a[], int left,int right)
{
	int result = a[left];
	for (int i = left+1; i < right; i++)
	{
		if (a[i] < result)
			result = a[i];
	}
	return result;
}

int Min(int a[], int length)
{
	if (a == nullptr || length <= 1)
		throw new exception("Invalid parameters");

	int left = 0;
	int right = length - 1;
	while (a[left] >=a[right])
	{
		if (right <= left+2)
			return a[right];
		     
		int mid = (left + right) / 2;
		if (a[right] == a[left]
			&& a[mid] == a[right])
			return MinInOder(a, left,right);
		if (a[mid] >= a[left])
			left = mid;
		else if (a[mid] <= a[right])
			right = mid;

	}
	return a[right];
}

int main()
{
	int a[] = { 1,1,1,1,0,1,1,1,1 };
	int min=Min(a, 6);
	cout << min << endl;
	system("pause");

}

猜你喜欢

转载自blog.csdn.net/summerlq/article/details/81562969