面试题8求旋转数组的最小值

//======================以下为自己实现=======================

#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)。

下面我们来考虑一些特殊情况:

  1. 若序列本身有序,若仍然采用上述算法,则会将倒数第二个元素误判为最小值。因此,如果数组的第一个元素小于最后一个元素时就认为数组有序,第一个元素即为最小值。
  2. 若数组的第一个元素和最后一个元素相等,则断点可能在中点的前半段,也可能在后半段,此时需要遍历数组求得最小值。
  1. /**
  2. * 获取旋转数组的最小值
  3. * 旋转数组:在一个递增数组的任意一个位置切一刀,
  4. * 再把第一个数组放到第二个数组的后面,
  5. * 这样生成的数组就是旋转数组。
  6. * @author chibozhou
  7. */
  8. public class GetMin {
  9. private static int min;
  10. /**
  11. * 获取旋转数组的最小值
  12. * @param arr 输入的旋转数组
  13. * @param start 数组的起始下标
  14. * @param end 数组的结束下标
  15. * @param min 搜索结果最小值
  16. */
  17. public static void getMin(int[] arr,int start,int end,Int min){
  18. //健壮性判断,数组不能为空
  19. if(arr== null || arr.length<= 0){
  20. System.out.println( "数组为空!");
  21. return ;
  22. }
  23. //健壮性判断,start不能>end
  24. if(start< 0 || end< 0 || start>end){
  25. System.out.println( "start、end非法!");
  26. return;
  27. }
  28. //健壮性判断,min不能为空
  29. if(min== null){
  30. System.out.println( "min为空!");
  31. return;
  32. }
  33. //若数组首<尾,则本身有序
  34. if(arr[start]<arr[end]){
  35. System.out.println( "数组本身有序");
  36. min.setMin(arr[start]);
  37. return;
  38. }
  39. //若数组首=尾,则断点位置不确定
  40. if(arr[start]==arr[end]){
  41. //遍历数组,寻找最小值
  42. int i = start;
  43. while(arr[i]<=arr[i+ 1] && i<end){
  44. i++;
  45. }
  46. //输出最小值
  47. min.setMin(arr[++i]);
  48. }
  49. //若数组首>尾,则断点位置可以确定(要么在中点前,要么在中点后)
  50. if(arr[start]>arr[end]){
  51. //获取中点
  52. int mid = (start+end)/ 2;
  53. //若数组首<中点,则断点在后半段
  54. if(arr[start]<arr[mid]){
  55. start = mid+ 1;
  56. }
  57. else if(arr[start]>arr[end]){
  58. end = mid- 1;
  59. }
  60. else{ //arr[start]=arr[end]
  61. start = mid+ 1;
  62. }
  63. //若start和end相邻,则比较一下选出小的
  64. if(start+ 1==end){
  65. if(arr[start]>arr[end]){
  66. min.setMin(arr[end]);
  67. }
  68. else{
  69. min.setMin(arr[start]);
  70. }
  71. return;
  72. }
  73. getMin(arr,start,end,min);
  74. }
  75. }
  76. /**
  77. * 测试
  78. */
  79. public static void main(String[] args){
  80. int[] a = new int[]{ 5, 5, 5, 1, 1, 1, 2, 3, 4};
  81. Int min = new Int();
  82. getMin(a, 0, a.length- 1, min);
  83. }
  84. }
<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;}}


猜你喜欢

转载自blog.csdn.net/qq_20398345/article/details/80879272