二分查找实现旋转数组的最小元素

题目:

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

示例 1:

输入:[3,4,5,1,2]
输出:1

示例 2:

输入:[2,2,2,0,1]
输出:0

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof

思路1:

  • 题目要求很简单,就是求一个数组的最小数,直接暴力破解变量一遍:
    实现代码:
int minArray(vector<int>& numbers) {
    
    
	if (numbers.size() == 1 || numbers[0] < numbers[numbers.size() - 1])
		return numbers[0];
	int right = numbers.size() - 1;
	// 从后往前遍历,遇到最小数跳出循环
	while (right > 0 && numbers[right - 1] <= numbers[right]) right--;	
	return numbers[right];
}

该方法时间复杂度是 O(n)

思路2:

  • 数组是递增排序的数组的一个旋转,旋转之后部分数组还是递增的,如:
    ( 4,5),(1,2,3)
  • 题目说若干个,也有可能是零个,存在这个情况:1,2,3,4,5
  • 既然是有序数组,可以利用二分查找的方法,只要处理好左右索引 i,j分别
    处在一个或者两个递增数组的情况就好了。
    实现代码:
int minArray(vector<int>& numbers) {
    
    
	int i = 0, j = numbers.size() - 1;
	int mid;
	while (i < j) {
    
    
		//情况有两种,一种是 i,j在同一个递增数组,另一种是两个
		mid = (i + j) / 2;
		//如果两个子数组,左数组大于等于右边元素,可以直接用 numbers[j]做比较
		if (numbers[mid] > numbers[j]) {
    
    
			i = mid + 1;	// 缩小左边范围
		}
		else if (numbers[mid] == numbers[j]) {
    
    
			j--;	//存在多个元素相等的情况,需要不断缩小排查
		}
		else {
    
    
			j = mid;	// numbers[mid] < numbers[j]时,缩小右边的范围
		}
	}
	return numbers[j];
}

时间复杂度O(logn)

猜你喜欢

转载自blog.csdn.net/h799710/article/details/107512588
今日推荐