• 剑指offer——面试题11:旋转数组的最小数字


     1 #include"iostream"
     2 using namespace std;
     3 
     4 int GetMinNumber(int *data,int len)
     5 {
     6     int left=0,right=len-1,mid;
     7 
     8     while(left<right-1)
     9     {
    10         mid=(left+right)/2;
    11         if(data[mid]>=data[left])
    12             left=mid;
    13         else if(data[mid]<data[right])
    14             right=mid;
    15     }
    16     return data[right];
    17 }
    18 
    19 void Test1()
    20 {
    21     cout<<"Test1:";
    22     int data[]={3,4,5,1,2};
    23     if(GetMinNumber(data,5)==1)
    24         cout<<"passed."<<endl;
    25     else
    26         cout<<"failed."<<endl;
    27 }
    28 
    29 void Test2()
    30 {
    31     cout<<"Test2:";
    32     int data[]={3,4,5,6,1,2};
    33     if(GetMinNumber(data,6)==1)
    34         cout<<"passed."<<endl;
    35     else
    36         cout<<"failed."<<endl;
    37 }
    38 
    39 void Test3()
    40 {
    41     cout<<"Test3:";
    42     int data[]={2,1};
    43     if(GetMinNumber(data,2)==1)
    44         cout<<"passed."<<endl;
    45     else
    46         cout<<"failed."<<endl;
    47 }
    48 
    49 int main()
    50 {
    51     Test1();
    52     Test2();
    53     Test3();
    54     return 0;
    55 }
    View Code

    官方答案:

      1 // 面试题11:旋转数组的最小数字
      2 // 题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
      3 // 输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如数组
      4 // {3, 4, 5, 1, 2}为{1, 2, 3, 4, 5}的一个旋转,该数组的最小值为1。
      5 
      6 #include <cstdio>
      7 #include <exception>
      8 
      9 int MinInOrder(int* numbers, int index1, int index2);
     10 
     11 int Min(int* numbers, int length)
     12 {
     13     if(numbers == nullptr || length <= 0)
     14         throw new std::exception("Invalid parameters");
     15  
     16     int index1 = 0;
     17     int index2 = length - 1;
     18     int indexMid = index1;
     19     while(numbers[index1] >= numbers[index2])
     20     {
     21         // 如果index1和index2指向相邻的两个数,
     22         // 则index1指向第一个递增子数组的最后一个数字,
     23         // index2指向第二个子数组的第一个数字,也就是数组中的最小数字
     24         if(index2 - index1 == 1)
     25         {
     26             indexMid = index2;
     27             break;
     28         }
     29  
     30         // 如果下标为index1、index2和indexMid指向的三个数字相等,
     31         // 则只能顺序查找
     32         indexMid = (index1 + index2) / 2;
     33         if(numbers[index1] == numbers[index2] && numbers[indexMid] == numbers[index1])
     34             return MinInOrder(numbers, index1, index2);
     35 
     36         // 缩小查找范围
     37         if(numbers[indexMid] >= numbers[index1])
     38             index1 = indexMid;
     39         else if(numbers[indexMid] <= numbers[index2])
     40             index2 = indexMid;
     41     }
     42  
     43     return numbers[indexMid];
     44 }
     45 
     46 int MinInOrder(int* numbers, int index1, int index2)
     47 {
     48     int result = numbers[index1];
     49     for(int i = index1 + 1; i <= index2; ++i)
     50     {
     51         if(result > numbers[i])
     52             result = numbers[i];
     53     }
     54 
     55     return result;
     56 }
     57 
     58 // ====================测试代码====================
     59 void Test(int* numbers, int length, int expected)
     60 {
     61     int result = 0;
     62     try
     63     {
     64         result = Min(numbers, length);
     65 
     66         for(int i = 0; i < length; ++i)
     67             printf("%d ", numbers[i]);
     68 
     69         if(result == expected)
     70             printf("	passed
    ");
     71         else
     72             printf("	failed
    ");
     73     }
     74     catch (...)
     75     {
     76         if(numbers == nullptr)
     77             printf("Test passed.
    ");
     78         else
     79             printf("Test failed.
    ");
     80     }
     81 }
     82 
     83 int main(int argc, char* argv[])
     84 {
     85     // 典型输入,单调升序的数组的一个旋转
     86     int array1[] = { 3, 4, 5, 1, 2 };
     87     Test(array1, sizeof(array1) / sizeof(int), 1);
     88 
     89     // 有重复数字,并且重复的数字刚好的最小的数字
     90     int array2[] = { 3, 4, 5, 1, 1, 2 };
     91     Test(array2, sizeof(array2) / sizeof(int), 1);
     92 
     93     // 有重复数字,但重复的数字不是第一个数字和最后一个数字
     94     int array3[] = { 3, 4, 5, 1, 2, 2 };
     95     Test(array3, sizeof(array3) / sizeof(int), 1);
     96 
     97     // 有重复的数字,并且重复的数字刚好是第一个数字和最后一个数字
     98     int array4[] = { 1, 0, 1, 1, 1 };
     99     Test(array4, sizeof(array4) / sizeof(int), 0);
    100 
    101     // 单调升序数组,旋转0个元素,也就是单调升序数组本身
    102     int array5[] = { 1, 2, 3, 4, 5 };
    103     Test(array5, sizeof(array5) / sizeof(int), 1);
    104 
    105     // 数组中只有一个数字
    106     int array6[] = { 2 };
    107     Test(array6, sizeof(array6) / sizeof(int), 2);
    108 
    109     // 输入nullptr
    110     Test(nullptr, 0, 0);
    111 
    112     return 0;
    113 }
    View Code

    与官方答案相比较,我少考虑了很多种特殊情况,相差甚远。

  • 相关阅读:
    为了抓包某APP所做的尝试(to be continued)
    VirtualBox的使用的一些Tips 网络配置|硬盘扩充
    斜线和反斜线简要历史,为什么windows和unix采用不同的路径分隔符
    求出二维数组主对角线、次对角线以及周边元素之和
    C#计算两个时间的时间差,精确到年月日时分秒
    C#获取MP3,WMA信息
    C#窗体随意移动
    DEV GridControl小结
    DEV 皮肤的使用
    C#窗体阴影
  • 原文地址:https://www.cnblogs.com/acm-jing/p/10391329.html
Copyright © 2020-2023  润新知