【题目】

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

【分析】

这道题最直观的解法并不难。从头到尾遍历数组一次,就能找出最小的元素,时间复杂度显然是O(N)。但这个思路没有利用输入数组的特性,我们应该能找到更好的解法。

我们容易想到二分查找,其时间复杂度为O(logn)。这个问题是否可以运用二分查找呢?答案是肯定的。观察一下数组的特性,首先递增(称为递增a),然后突然下降到最小值,然后再递增(称为递增b)。

对于一般的情况,假设A为输入数组,left 和 right 为数组左右边界的坐标,考察中间位置的值A[mid] 。

(1)如果A[mid] >= A[left],表明处于递增a,因此调整left = mid。

(2)如果A[mid] <= A[right],表明处于递增b,调整right = mid。

经过若干次调整以后,left指向递增a的最后一个元素,right指向递增b的第一个元素;此时left和right相邻,即right-left==1,那么较小的一个A[right]就是数组的最小值。

但是还有特殊情况需要考虑:

(3)旋转元素个数为0,即旋转数组本身就是递增序列。即A[left]<A[right],那么A[left]就是最小值。

(4)如果A[left]== A[mid]== A[right],若果仍然按照(1)(2)的做法,那么最终left和right会指向同一个元素,即left=right,而无法跳出循环,此时就要使用常规方法求解。

举几个具体例子就清楚了:

{3, 4, 5, 1, 2},A[mid] >A[left]> A[right],最终left==right-1,最小值为1;符合(1,2)。

{3, 4, 5, 1, 3},A[mid] >A[left]=A[right],最终left==right-1,最小值为1;符合(1,2)。

{3, 3, 3, 1,2},A[mid]=A[left]>A[right],最终left==right-1,最小值为1;符合(1,2)。

{3, 3, 3, 1,3},A[mid]=A[left]=A[right],常规方法求解,最小值为1;符合(4)。

{1, 2, 3, 4, 5},A[left]<A[right],最小值为1;符合(3)。

【代码】

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
 
// 42_GetRotationArrayMinValue.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
using namespace std;

// Get min value from data[left] to data[right]
int MinInOrder(int *data, int left, int right)
{
    int minValue = data[left];
    ; i < right; ++i)
    {
        if (data[i] < minValue)
            minValue = data[i];
    }
    return minValue;
}
/*
get min value of rotation array
{3, 4, 5, 1, 2},A[mid] >A[left]> A[right],left==right-1,min=A[right]=1。
{3, 4, 5, 1, 3},A[mid] >A[left]=A[right],left==right-1,min=A[right]=1。
{3, 3, 3, 1,2},A[mid]=A[left]>A[right],left==right-1,min=A[right]=1。
***{3, 3, 3, 1,3},A[mid]=A[left]=A[right],use normal function to get min=1。
***{1, 2, 3, 4, 5},A[left]<A[right],min=A[left]=1。
*/
int GetRotationArrayMinValue(int *A, int n)
{
    )
        throw new std::exception("Invalid params!");
    ;
    ;
    if (A[left] < A[right])
        return A[left];
    while(A[left] >= A[right])
    {
        // final break out here
)
            return A[right];

;

// special case
        // process A[mid]=A[left]=A[right]
        if (A[left] == A[mid] && A[mid] == A[right])
        {
            return MinInOrder(A, left, right);
        }

// normal cases
        if (A[mid] >= A[left])
            left = mid;
        else if (A[mid] <= A[right])
            right = mid;
    }
}

void test_base(int *data, int n)
{
    int result = GetRotationArrayMinValue(data, n);
    cout << result << endl;
}

void test_case1()
{
    };
    int length = sizeof(data) / sizeof(int);
    test_base(data, length);
}

void test_case2()
{
    };
    int length = sizeof(data) / sizeof(int);
    test_base(data, length);
}
void test_case3()
{
    };
    int length = sizeof(data) / sizeof(int);
    test_base(data, length);
}
void test_case4()
{
    };
    int length = sizeof(data) / sizeof(int);
    test_base(data, length);
}
void test_case5()
{
    };
    int length = sizeof(data) / sizeof(int);
    test_base(data, length);
}

void test_main()
{
    test_case1();
    test_case2();
    test_case3();
    test_case4();
    test_case5();
}

int _tmain(int argc, _TCHAR *argv[])
{
    test_main();
    ;
}

最后总结一下本面试题的主要考点:

1. 考查对二分查找的理解。本题变换了二分查找的条件,输入数组不是排序的,而是排序数组的一个旋转。这要求我们对二分查找的过程有深刻的理解。

2. 考查沟通学习能力。如果在面试过程中,面试官提出新的概念,比如“数组的旋转”,我们要主动和面试官沟通,多问几个问题把概念弄清楚。

3. 考查思维的全面性。比如要考虑到:(1)排序数组本身是数组旋转的一个特例;(2)要考虑到数组中有相同数字的特例。如果不能很好处理这些特例,就很难写出让面试官满意的完美代码。

【参考】

http://zhedahht.blog.163.com/blog/static/25411174200952765120546/

http://zhuyanfeng.com/archives/2923

http://blog.csdn.net/wuzhekai1985/article/details/6733700

42.旋转数组的最小元素[Get min value of rotated array]的更多相关文章

  1. 【Offer】[11] 【旋转数组的最小元素】

    题目描述 思路分析 Java代码 代码链接 题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4, ...

  2. 九度OJ 1386 旋转数组的最小数字 【算法】

    题目地址:http://ac.jobdu.com/problem.php?pid=1386 题目描述: 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序的数组的一个旋 ...

  3. 剑指Offer 旋转数组的最小数字

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

  4. 剑指offer-面试题8.旋转数组的最小数字

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

  5. 旋转数组的最小数字(JAVA)

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

  6. 剑指offer六之求旋转数组的最小数字

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

  7. 《剑指offer》第十一题(旋转数组的最小数字)

    // 面试题:旋转数组的最小数字 // 题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. // 输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如数组 // {3, ...

  8. (剑指Offer)面试题8:旋转数组的最小数字

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

  9. 旋转数组的最小数字(C++ 和 Python 实现)

    (说明:本博客中的题目.题目详细说明及参考代码均摘自 “何海涛<剑指Offer:名企面试官精讲典型编程题>2012年”) 题目 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的 ...

随机推荐

  1. 小菜鸟 学MQ(二)

    mq服务启动以后 接着要做的事情就是 [发送]和[接受]消息. 首先有两种不同类型的Message:Topic,Queue 第一种Topic JMS规范定义了,Topic需要实现 发布和订阅两个功能, ...

  2. Java基础-String 存储机制管理

    JVM运行的时候,将内存分为两个部分,一部分是堆,一部分是栈.堆中存放的是创建对象,而栈中存放的则是方法调用过程中的局部变量或引用.在设计JAVA字符串对象内存实现的时候,在堆中又开辟了一块很小的内存 ...

  3. 【BZOJ-3172】单词 AC自动机

    3172: [Tjoi2013]单词 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 2567  Solved: 1200[Submit][Status ...

  4. BZOJ3229 石子合并

    Description 在一个操场上摆放着一排N堆石子.现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分. 试设计一个算法,计算出将N堆石 ...

  5. POJ 2559 Largest Rectangle in a Histogram

    Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 18942   Accepted: 6083 Description A hi ...

  6. python运行报错:urllib2.URLError: <urlopen error [Errno 10061] >

    Traceback (most recent call last): File "F:\adt-bundle-windows-x86_64-20140702\eclipse\workspac ...

  7. hdu acmsteps 2.1.8 Leftmost Digit

    Leftmost Digit Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Tota ...

  8. Android实现控件动画效果

    MainActivity.java public class MainActivity extends AppCompatActivity { private ImageView iv; privat ...

  9. Linux下安装Nginx详细图解教程

    什么是Nginx? Nginx ("engine x") 是一个高性能的 HTTP 和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器,在高连接并发的情况下N ...

  10. yii 10.16

    什么是框架? a)         框架就是一个半成品,一个帮助我们完成业务流程的程序 b)        框架融合了很多的功能,但是不会给我们具体功能模块 c)         我们需要在框架的基础 ...