码迷,mamicode.com
首页 > 编程语言 > 详细

旋转数组的最小值

时间:2016-04-18 13:40:58      阅读:164      评论:0      收藏:0      [点我收藏+]

标签:

问题

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

思路

  这道题最直观的解法并不难。从头到尾遍历数组一次,就能找出最小的元素,时间复杂度显然是O(n)。但这个思路没有利用输入数组的特性。既然有时间复杂度更小的算法,我们容易想到二分查找,因为它的时间复杂度为O(logn)。这个问题是否可以运用二分查找呢?答案是肯定的。观察一下数组的特性,首先递增(称为递增a),然后突然下降到最小值,然后再递增(称为递增b)。当然还有一种特殊情况,就是数组递增,中间没有下降,即旋转元素个数为0。

  一般解法:找到中间下标,如果数组开始值小于中间下标对应的值,则表示中间下标属于第一个第一个递增,另开始下标等于中间下标,相反,如果中间下标对应的值小于结尾值,则表明,中间下标输入第二个递增,另结尾下标等于中间下标。直到开始下标和结尾下标相邻。

  特殊情况:旋转个数为0,例如{1,2,3,4,5},则可以通过第一个值小于最后一个值判断,直接输出第一个值。

package offer008;

import java.util.Scanner;

/** 
 * @Title: Main.java
 * @Package: offer008
 * @Description 旋转数组的最小数字
 * @author Han
 * @date 2016-4-18 上午10:39:35 
 * @version V1.0
 */ 
      
public class Main {
    
    public static void main(String[] args) {
        
        Scanner scanner = new Scanner(System.in);
        int[] arr = null;
        int count = 0;
        
        while(scanner.hasNext()){
            
            //输入数组的大小
            count = scanner.nextInt();
            arr = new int[count];
            
            //输入数组
            for(int i = 0; i < count; i++){
                
                arr[i] = scanner.nextInt();
            }
            System.out.println(min(arr));
        }
    }
    
     
    /** 
     * @Description 得到旋转数组中的最小值
     * @author Han
     * @param arr
     * @return  min
     */
          
    private static int min(int[] arr){
        
        //判断数组是否为空,长度是否为0
        if(arr == null || arr.length == 0){
            
            throw new RuntimeException("Error Input");
        }
        
        //头下标
        int startIndex = 0;
        //尾下标
        int endIndex = arr.length - 1;
        //中间下标
        int middleIndex = 0;
        
        //如果数组中的第一个值小于了最后一个值,则表明该数组为一个递增数组,直接输出第一个元素即可
        while(arr[startIndex] >= arr[endIndex]){

            //若该startIndex和endIndex相邻成立则表示endIndex指向的数字为最小值
            if(endIndex - startIndex == 1){
                
                startIndex = endIndex;
                break;
            }
            
            middleIndex = (startIndex + endIndex) / 2;
            
            //如果三个值相等,类似于1 0 1 1 1 1,则需要需要通过顺序查找出最小值
            if(arr[middleIndex] == arr[startIndex] && arr[middleIndex] == arr[endIndex]){
                
                return minByOrder(arr, startIndex, endIndex);
            }
            
            //若中间值大于startIndex指向的值,则移动startIndex到中间值
            if(arr[middleIndex] >= arr[startIndex]){
                
                startIndex = middleIndex;
            }else if(arr[middleIndex] <= arr[endIndex]){
                
                endIndex = middleIndex;
            }
        }
        
        return arr[startIndex];
    }

     
    /** 
     * @Description 顺序查找出最小值
     * @author Han
     * @param arr
     * @param startIndex
     * @param endIndex
     * @return  
     */
          
    private static int minByOrder(int[] arr, int startIndex, int endIndex) {

        int min = arr[startIndex];
        
        for(int i = startIndex + 1; i <= endIndex; i++){
            
            if(arr[i] < min){
                
                min = arr[i];
            }
        }
        
        return min;
    }
}

结果

技术分享

  

旋转数组的最小值

标签:

原文地址:http://www.cnblogs.com/a294098789/p/5404062.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!