剑指offer面试题8

来源:互联网 发布:淘宝极速退款没有了 编辑:程序博客网 时间:2024/05/16 06:02

面试题8:旋转数组的最小数字

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

预备知识:

排序: 归并排序,快速排序,插入排序,冒泡排序

查找:二分查找,顺序查找,哈希表查找,二叉树排序树查找

指标:额外空间消耗,平均时间复杂度和最差时间复杂度

实现方式:递归和循环两种方式

位运算:与&,或|,异或^,左移<<,右移>>


思路:首先要弄清楚题目的意思以及相关的概念,接着需要自己通过一个简单的例子进行具体分析如何查找,最后寻找特殊的例子,如边界值或特殊输入进行分析即可,这里需要注意临界条件。

算法实现:

#include "stdafx.h"#include<exception> //C++异常处理int MinInOrder(int* numbers, int index1, int index2);int Min(int* numbers, int length){    if(numbers == NULL || length <= 0)        throw new std::exception("Invalid parameters"); //异常处理类class exception;    //在C/C++数组索引是从0开始的    int index1 = 0;            //开头元素索引    int index2 = length - 1;   //结束元素索引    int indexMid = index1;     //当前面0个元素搬到最后面,即保存不变的时候    while(numbers[index1] >= numbers[index2]) //临界条件    {        // 如果index1和index2指向相邻的两个数,        // 则index1指向第一个递增子数组的最后一个数字,        // index2指向第二个子数组的第一个数字,也就是数组中的最小数字        if(index2 - index1 == 1) //相邻元素        {            indexMid = index2;            break;        }         // 如果下标为index1、index2和indexMid指向的三个数字相等,        // 则只能顺序查找        indexMid = (index1 + index2) / 2;        if(numbers[index1] == numbers[index2] && numbers[indexMid] == numbers[index1]) //特例的情况            return MinInOrder(numbers, index1, index2); //顺序查找        // 缩小查找范围        if(numbers[indexMid] >= numbers[index1])     //中间元素大于等于前面的元素,说明这个元素位于第一递增数组中            index1 = indexMid;        else if(numbers[indexMid] <= numbers[index2])//中间元素小于等于后面的元素,说明这个元素位于第二递增数组中            index2 = indexMid;    }     return numbers[indexMid];}//顺序查找最小值int MinInOrder(int* numbers, int index1, int index2){    int result = numbers[index1];    for(int i = index1 + 1; i <= index2; ++i) //在数组中遍历每一个值    {        if(result > numbers[i])            result = numbers[i];    }    return result;}// ====================测试代码====================void Test(int* numbers, int length, int expected){    int result = 0;    try    {        result = Min(numbers, length);  //二分查找最小        for(int i = 0; i < length; ++i)            printf("%d ", numbers[i]);        if(result == expected)            printf("\tpassed\n");        else            printf("\tfailed\n");    }    catch (...)    {        if(numbers == NULL)  //特殊输入测试            printf("Test passed.\n");        else            printf("Test failed.\n");    }}int _tmain(int argc, _TCHAR* argv[]){    // 典型输入,单调升序的数组的一个旋转    int array1[] = {3, 4, 5, 1, 2};    Test(array1, sizeof(array1) / sizeof(int), 1);    // 有重复数字,并且重复的数字刚好的最小的数字    int array2[] = {3, 4, 5, 1, 1, 2};    Test(array2, sizeof(array2) / sizeof(int), 1);    // 有重复数字,但重复的数字不是第一个数字和最后一个数字    int array3[] = {3, 4, 5, 1, 2, 2};    Test(array3, sizeof(array3) / sizeof(int), 1);    // 有重复的数字,并且重复的数字刚好是第一个数字和最后一个数字    int array4[] = {1, 0, 1, 1, 1};    Test(array4, sizeof(array4) / sizeof(int), 0);    // 单调升序数组,旋转0个元素,也就是单调升序数组本身    int array5[] = {1, 2, 3, 4, 5};    Test(array5, sizeof(array5) / sizeof(int), 1);    // 数组中只有一个数字    int array6[] = {2};    Test(array6, sizeof(array6) / sizeof(int), 2);    // 输入NULL    Test(NULL, 0, 0);    return 0;}


//***********************7月12日********************************************************//

// 面试题8.cpp : 定义控制台应用程序的入口点。////旋转数组的最小数字#include "stdafx.h"#include <exception>using namespace std;int Min_1(int* numbers, int length){if(numbers == NULL || length < 0)throw new std::exception("Invalid parameters");int index1 = 0;            //第一个指针int index2 = length - 1;   //第二个指针int indexMid = index1;while(numbers[index1] >= numbers[index2]){if(index2 - index1 == 1 ){indexMid = index2;break;}if (index1 == index2){indexMid = index2;break;}indexMid = (index1 + index2) / 2; //中间元素if (numbers[indexMid] >= numbers[index1])index1 = indexMid;else if (numbers[indexMid] <= numbers[index2])index2 = indexMid;}return  numbers[indexMid];}int MinInOrder(int* numbers, int index1, int index2);int Min_2(int* numbers, int length){if(numbers == NULL || length <= 0)throw new std::exception("Invalid parameters");int index1 = 0;int index2 = length -1;int indexMid = index1;while(numbers[index1] >= numbers[index2]){indexMid = (index1 + index2) / 2;  //中间的元素//如果这指针指向的3个元素相等,那么只能顺序查找了if(numbers[index1] == numbers[index2] && numbers[indexMid] == numbers[index1]){return MinInOrder(numbers, index1, index2);}if(numbers[indexMid] >= numbers[index1])index1 = indexMid;else if(numbers[indexMid] <= numbers[index2])index2 = indexMid;}}//顺序查找int MinInOrder(int* numbers, int index1, int index2){int result = numbers[index1];for(int i = index1 + 1; i <= index2; ++i){if(result > numbers[i])result = numbers[i];}return result;}/************测试1*************/void Test1(){int numbers[] = {3,4,5,6,7,8,9,-2,-1,1,2};int min = Min_1(numbers, sizeof(numbers)/sizeof(int));printf("min = %d\n", min);}//int numbers[] = {1,2,3,4,5,6}void Test2(){int numbers[] = {1,2,3,4,5,6}; //0次旋转int min = Min_1(numbers, sizeof(numbers)/sizeof(int));printf("min = %d\n", min);}//int numbers[]={111111}void Test3(){int numbers[] = {1,1,1,1,1,1};int min = Min_1(numbers, sizeof(numbers)/sizeof(int));printf("min = %d\n", min);}//int numbers[]={111000}void Test4(){int numbers[] = {1,1,1,0,0,0};int min = Min_1(numbers, sizeof(numbers)/sizeof(int));printf("min = %d\n", min);}//int numbers[]={111-211}void Test5(){int numbers[] = {1,1,1,-2,1,1};int min = Min_1(numbers, sizeof(numbers)/sizeof(int));printf("min = %d\n", min);}//int numbers[]={1-21111}void Test6(){int numbers[] = {1,-2,1,1,1,1};int min = Min_1(numbers, sizeof(numbers)/sizeof(int));printf("min = %d\n", min);}//int numbers[]={1}void Test7(){int numbers[] = {1};int min = Min_1(numbers, sizeof(numbers)/sizeof(int));printf("min = %d\n", min);}//int numbers[]={1}void Test8(){try{int min = Min_1(NULL, 0);printf("min = %d\n", min);} catch(...){printf("无效参数\n");}}/*********测试2*********///int numbers[]={1}void Test1_1(){int numbers[] = {1,-2,1,1,1,1};int min = Min_2(numbers, sizeof(numbers)/sizeof(int));printf("min = %d\n", min);}int _tmain(int argc, _TCHAR* argv[]){//Test1();//Test2();//Test3();//Test4();//Test5();Test6();//Test7();Test8();Test1_1();return 0;}



0 0
原创粉丝点击