查找旋转数组的最小元素

/******************************************************************
    把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
    输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。
    例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
    NOTE:给出的所有元素都大于0,若数组大小为0,请返回0
*******************************************************************/

实现: 1.先实现函数指定移位,旋转数组。 以{1,2,3,4,5}为例

2.旋转后的数组分为两个有序递增序列{3,4, 5}和{1,2}

3.采用二分查找(特例的有序序列)的方法。指定两个变量 left 和 right, 指向查询块的首尾

4.定义mid = (left +right) / 2;

{3,4,5}                   {1,2}

5.如果 mid 对应的值(5)大于 left 的(3),则最小值在右边序列,在数组的右边部分进行查找,重置 left = mid

{5}                         {1,2,3,4}

6.如果 mid 对应的值(2)小于 left 的(5),则最小值在左边序列,在数组的左边进行查找,重置 right = mid

head.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

 Main.c

#include "Head.h"

/******************************************************************
	把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 
	输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 
	例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
	NOTE:给出的所有元素都大于0,若数组大小为0,请返回0
*******************************************************************/
#define SIZE 9
// 旋转一个非递减数组 
// 将数组的前 n 位搬到数组的末尾, 完成数组的旋转
void RotateArray(int arr[], int n) {
	assert(n > 0 && n <= SIZE);

	for (int i = 0; i < n; ++i) {
		// 外层循环控制移动的若干个元素
		// 交换首尾元素、内循环交换中间的元素
		int tmp = arr[0];
		for (int j = 0; j < SIZE - 1; ++j) {
			arr[j] = arr[j + 1];
		}
		arr[SIZE - 1] = tmp;     
	}
}

// 旋转数组的最小元素
// 此时为两个递增序列合起来的有序数组,前一部分递增、后一部分递增. 假设不知道分界值
// 查找最小元素,采用二分查找.
int minNumberInRotateArray(int arr[]) {
	if (SIZE == 0){
		return 0;
	}
	int left = 0, right = SIZE - 1;
	int mid, ret;
	// 假设
	// {3, 4, 5} {1, 2}
	while (1) {
		mid = (left + right) / 2;

		if (right - left <= 1) {
			return arr[right];
		}

		if (arr[mid] > arr[left]) {
			// 最小值在右边部分
			left = mid;
		}
		else {
			right = mid;
		}
	}

}

int main() {

	int arr[SIZE] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	RotateArray(arr, 8);
	int ret = minNumberInRotateArray(arr);
	system("pause");
	return 0;
}

测试:

使用{1,2,3,4,5,6,7,8,9}

旋转后{7,8,9,1,2,3,4,5,6}

1. left = 7, right = 6, mid = 2

2.mid < left 最小值在左边。 [left] = 7, [right] =  [mid] = 2, [mid] =  9

                      {7,8,9,1,2}

3.mid > left 最小值在右边。 [left] = [mid] = 9, [right] = 2, [mid] = 1

                     {9,1,2}

4.mid < left 最小值在左边。 [left] = 9, [right] = [mid] = 1, [mid] = 9

                     {9,1}

5.right - mid <= 1.循环结束,最小元素为 [right] 对应的元素

猜你喜欢

转载自blog.csdn.net/Q_feifeiyu/article/details/88615037