//======================以下为自己实现=======================
#include <stdio.h>
#include <stdlib.h>
void getMin(int *s, int start, int end, int *min)
{
if(s==NULL || start < 0 || end < 0 || start > end)
{
return;
}
if(start == end)
{
*min = s[start];
return;
}
if(s[start] < s[end])
{
*min=s[start];
return;
}
//若数组首=尾,则断点位置不确定
if(s[start] == s[end])
{
int i=start;
//遍历数组,寻找最小值
while(s[i] <=s[i+1] && i<end)
{
i++;
}
//输出最小值
*min=s[++i];
return;
}
//若数组首>尾,则断点位置可以确定(要么在中点前,要么在中点后)
if(s[start] > s[end])
{
//获取中点
int mid = (end+start)/2;
//若数组首>中点,则断点在前半段
if(s[start] > s[mid])
{
end = mid-1;
}
//若数组首<=中点,则断点在后半段
else if(s[start] <=s[mid])
{
start=mid+1;
}
//若start和end相邻,则比较一下选出小的
if(start+1==end){
if(s[start]>s[end]){
*min = s[end];
}
else{
*min = s[start];
}
return;
}
getMin(s, start, end, min);
}
}
int main(int argc, char *argv[])
{
int a[9] = {5,5,5,1,1,1,2,3,4};
int min;
getMin(a, 0, 8, &min);
printf("min = %d\n", min);
system("PAUSE");
return 0;
}
//=======================以下为转载==========================
https://blog.csdn.net/u010425776/article/details/50817174
题目:将一个非递减序列的某一处切一刀,再把前半段序列放到后半段序列的后面,这样组成的新序列叫做“旋转数组”。要求获取一个旋转数组的最小值。
这本质上是一个求最值的问题,最简单的方法就是顺序遍历数组,从中找出最小值,该方法的时间复杂度为O(n)。但这种方法会被面试官鄙视的,所以我们寻找更为高效的办法。
这道题给的数组是一个“旋转数组”,旋转数组是将一个非递减数组切成两个数组后重新组装而成的,旋转数组的前半段所有元素值均大于等于后半段元素的值,两段的分界点就是最小值。
要寻找分界点,可以采用对半搜索,若第一个元素的值小于中点元素值,则断点在后半段,否则断点在前半段,若当前数组只剩下两个元素时,找出其中较小一个即是答案。时间复杂度为O(logn)。
下面我们来考虑一些特殊情况:
- 若序列本身有序,若仍然采用上述算法,则会将倒数第二个元素误判为最小值。因此,如果数组的第一个元素小于最后一个元素时就认为数组有序,第一个元素即为最小值。
- 若数组的第一个元素和最后一个元素相等,则断点可能在中点的前半段,也可能在后半段,此时需要遍历数组求得最小值。
-
/**
-
* 获取旋转数组的最小值
-
* 旋转数组:在一个递增数组的任意一个位置切一刀,
-
* 再把第一个数组放到第二个数组的后面,
-
* 这样生成的数组就是旋转数组。
-
* @author chibozhou
-
*/
-
public class GetMin {
-
private static int min;
-
/**
-
* 获取旋转数组的最小值
-
* @param arr 输入的旋转数组
-
* @param start 数组的起始下标
-
* @param end 数组的结束下标
-
* @param min 搜索结果最小值
-
*/
-
public static void getMin(int[] arr,int start,int end,Int min){
-
//健壮性判断,数组不能为空
-
if(arr== null || arr.length<= 0){
-
System.out.println( "数组为空!");
-
return ;
-
}
-
//健壮性判断,start不能>end
-
if(start< 0 || end< 0 || start>end){
-
System.out.println( "start、end非法!");
-
return;
-
}
-
//健壮性判断,min不能为空
-
if(min== null){
-
System.out.println( "min为空!");
-
return;
-
}
-
-
//若数组首<尾,则本身有序
-
if(arr[start]<arr[end]){
-
System.out.println( "数组本身有序");
-
min.setMin(arr[start]);
-
return;
-
}
-
-
//若数组首=尾,则断点位置不确定
-
if(arr[start]==arr[end]){
-
//遍历数组,寻找最小值
-
int i = start;
-
while(arr[i]<=arr[i+ 1] && i<end){
-
i++;
-
}
-
//输出最小值
-
min.setMin(arr[++i]);
-
}
-
-
//若数组首>尾,则断点位置可以确定(要么在中点前,要么在中点后)
-
if(arr[start]>arr[end]){
-
//获取中点
-
int mid = (start+end)/ 2;
-
//若数组首<中点,则断点在后半段
-
if(arr[start]<arr[mid]){
-
start = mid+ 1;
-
}
-
else if(arr[start]>arr[end]){
-
end = mid- 1;
-
}
-
else{ //arr[start]=arr[end]
-
start = mid+ 1;
-
}
-
-
//若start和end相邻,则比较一下选出小的
-
if(start+ 1==end){
-
if(arr[start]>arr[end]){
-
min.setMin(arr[end]);
-
}
-
else{
-
min.setMin(arr[start]);
-
}
-
return;
-
}
-
getMin(arr,start,end,min);
-
}
-
}
-
-
-
-
-
/**
-
* 测试
-
*/
-
public static void main(String[] args){
-
int[] a = new int[]{ 5, 5, 5, 1, 1, 1, 2, 3, 4};
-
Int min = new Int();
-
getMin(a, 0, a.length- 1, min);
-
}
-
}
<pre code_snippet_id="1600005" snippet_file_name="blog_20160307_4_6262722" name="code" class="java">/**
* 本类用于设置最小值 * @author chibozhou */class Int{private int min;public int getMin() {return min;}public void setMin(int min) {this.min = min;}}