旋转数组的最小数字

题目:

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

分析;

       1. 可以从头遍历一遍,但是没有使用到递增数组这个条件,不是最优复杂度的解

       2. 可以仿照二分查找的思想,使得复杂度达到O(logn),该方法的思路如下:旋转数组前半部分递增排列,后半部分也递增排列,那么最小数就是数组的分界线。让一个指针指向旋转数组的头,一个指针指向旋转数组的尾,用二分查找的思路就可以找到最小的数值。

           但是此方法不能完全解决各种测试用例,例如对于数组{0,1,1,1,1}的两个旋转{1,1,1,0,1}和{1,0,1,1,1},使用上述方法时,由于选中间数据时直接将中间下标定义为2,那么就错过了最小的数字0,这样程序结果就是错误的。解决这个小问题的方式是:number[start] == numbers[mid] && numbers[mid] == numbers[end] 时,采用顺序遍历的方法来查找。

 

代码实现:

int MinInOrder(int *numbers, int index1, int index2)
{
	int min = numbers[index1];
	for (int i = index1; i <= index2; i++)
	{
		if (min > numbers[i])
			min = numbers[i];
	}
	return min;
}

int Min(int *numbers, int length)
{
	if (numbers == NULL || length <= 0)
		throw new std::exception("error");

	int index1 = 0;
	int index2 = length - 1;
	int indexMid = index1; //假如翻转了原数组的前0个数字,那么第一个就是最小的,所以初始为index1

	while (numbers[index1] >= numbers[index2])  //前面的数字大于后面的数字,数字翻转后,后半部分数据小于前半部分数据
	{
		if (index2 - index1 == 1) //两指针相邻,则最小值为第二个指针位置的数据
		{
			indexMid = index2;
			break;
		}	

		indexMid = (index1 + index2) / 2;
		
		//翻转数组中的特殊用例,使用依次遍历策略
		if (numbers[index2] == numbers[index1] && numbers[index1] == numbers[indexMid])
			return MinInOrder(numbers, index1, index2);

		if (numbers[indexMid] >= numbers[index1]) //最小值在indexMid的右边
			index1 = indexMid;
		else if (numbers[indexMid] <= numbers[index2]) //最小值在indexMid的左边
			index2 = indexMid;
	}
	return numbers[indexMid];
}

int main()
{
	//int arr[] = { 3, 4, 5, 1, 2 };
	//int arr[] = { 1, 0, 1, 1, 1 };
	int arr[] = { 1, 1, 1, 0, 1 };
	int len = sizeof(arr) / sizeof(arr[0]);
	cout << Min(arr, len) << endl;
	return 0;
}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值