8+查找一个旋转数组的最小元素

title:
查找一个旋转数组a中的最小元素(首尾下标:start,end)
旋转数组就是将一个有序数组的前n个元素移到数组的尾部,形成类似bitonic序列
(先递增再递减或者先递减再递增)的数组


thought:

方法:采用二分查找的方法(O(logn)),
     当中间值不小于第一个元素,则最小元素在中间值后面;
     当中间值不大于最末元素,则最大值在中间值前面(均包含中间值在内)
  
特例1:旋转数组仍是有序数组,即将原来数组中的前“0”个元素移到数组尾部
特例2: 当中间值与首位和末位元素三者相等时,判断不出最小元素在中间值之前还是之后,
            此种情况下只能采用顺序查找的方法


realize:(以递增数组为例)

1、先设置中间元素下标mid=start(处理特例1)
2、以a[start] >= a[end]为while循环条件:
     {
     如果首尾下标相邻或者相等,则mid就等于end,循环结束,返回a[mid];
     计算mid=(start +end)/2
     如果首尾元素和中间元素三者相等,则转向顺序查找函数来查找最小值
     如果a[mid] >= a[start],则最小元素在mid后面(包括mid)的序列,即start=mid
     如果a[mid] <= a[end],则最小元素在mid前面(包括mid)的序列,即end=mid
     }
 3、返回a[mid]

   

#include <iostream>
#include <iomanip>
using namespace std;
int find_min(int [],int Len);
int find_min_inorder(int [],int start,int end);  //顺序查找

int find_min(int a[],int Len)
{
	if(NULL == a || Len <= 0)
		throw new std::exception("Invaild array!");
	int  start = 0;
	int  end = Len-1;
	int mid = start;  //把中间元素初始化为首位元素是为了处理一个“特例”:把原递增数组的前“0”个元素移到末位(说明旋转数组仍然是递增数组))
	while (a[start] >= a[end])
	{
		if(end-start <= 1)
		{
			mid = end;
			break;
		}
		mid = (start +end)/2;
		if(a[start] == a[mid] && a[mid] == a[end])
			return find_min_inorder(a,start,end);
		if(a[mid] >= a[start])
			start = mid;
		else if(a[mid] <= a[end])
			end = mid;
	}
	return a[mid];
}

int find_min_inorder(int a[],int start,int end)
{
	int Min = a[start];
	for(int i = start;i <= end;i++)
	{
		if(a[i] < Min)
			Min = a[i];
	}
	return Min;
}

int main()
{
	int array_roate[] = {3,4,5,6,1,2,3};
	//int array_roate[] = {1,0,1,1,1};  //特例:中间元素和首尾元素三者相等(只能采用顺序查找的方法)
	//int array_roate[] = {1,2,3,4,5};  //旋转数组仍为顺序数组(需要将mid初始化为首位元素)
	int length = sizeof(array_roate)/sizeof(int);
	cout << "旋转数组如下:" << endl;
	for(int i = 0;i < length;i++)
		cout << setw(3) << array_roate[i];
	cout << endl;
	int Min = find_min(array_roate,length);
	cout << "旋转数组中的最小元素是:" << Min << endl;
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值