`
caoruntao
  • 浏览: 469335 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

旋转数组的最小元素

 
阅读更多

【转】http://zhedahht.blog.163.com/blog/static/25411174200952765120546/

 

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

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

         我们注意到旋转之后的数组实际上可以划分为两个排序的子数组,而且前面的子数组的元素都大于或者等于后面子数组的元素。我们还可以注意到最小的元素刚好是这两个子数组的分界线。我们试着用二元查找法的思路在寻找这个最小的元素。

         首先我们用两个指针,分别指向数组的第一个元素和最后一个元素。按照题目旋转的规则,第一个元素应该是大于或者等于最后一个元素的(这其实不完全对,还有特例。后面再讨论特例)。

接着我们得到处在数组中间的元素。如果该中间元素位于前面的递增子数组,那么它应该大于或者等于第一个指针指向的元素。此时数组中最小的元素应该位于该中间元素的后面。我们可以把第一指针指向该中间元素,这样可以缩小寻找的范围。同样,如果中间元素位于后面的递增子数组,那么它应该小于或者等于第二个指针指向的元素。此时该数组中最小的元素应该位于该中间元素的前面。我们可以把第二个指针指向该中间元素,这样同样可以缩小寻找的范围。我们接着再用更新之后的两个指针,去得到和比较新的中间元素,循环下去。

按照上述的思路,我们的第一个指针总是指向前面递增数组的元素,而第二个指针总是指向后面递增数组的元素。最后第一个指针将指向前面子数组的最后一个元素,而第二个指针会指向后面子数组的第一个元素。也就是它们最终会指向两个相邻的元素,而第二个指针指向的刚好是最小的元素。这就是循环结束的条件。

基于这个思路,我们可以写出如下代码:

// Get the minimum number of a roatation of a sorted array

int Min(int *numbers, int length)

{

    if(numbers == 0 || 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;

        }

 

        indexMid = (index1 + index2) / 2;

        if(numbers[indexMid] >= numbers[index1])

            index1 = indexMid;

        else if(numbers[indexMid] <= numbers[index2])

            index2 = indexMid;

    }

 

    return numbers[indexMid];

}

由于我们每次都把寻找的范围缩小一半,该算法的时间复杂度是O(logN)

值得注意的是,如果在面试现场写代码,通常我们需要用一些测试用例来验证代码是不是正确的,我们在验证的时候尽量能考虑全面些。像这道题,我们出来最简单测试用例之外,我们至少还需要考虑如下的情况:

1.              把数组前面的0个元素从最前面搬到最后面,也就是原数组不做改动,根据题目的规则这也是一个旋转,此时数组的第一个元素是大于小于或者等于最后一个元素的;

2.              排好序的数组中有可能有相等的元素,我们特别需要注意两种情况。一是旋转之后的数组中,第一个元素和最后一个元素是相等的;另外一种情况是最小的元素在数组中重复出现

3.              在前面的代码中,如果输入的数组不是一个排序数组的旋转,那将陷入死循环。因此我们需要跟面试官讨论是不是需要判断数组的有效性。在面试的时候,面试官讨论如何验证输入的有效性,能显示我们思维的严密性。本文假设在调用函数Min之前,已经验证过输入的有效性了。

最后需要指出的是,如果输入的数组指针是非法指针,我们是用异常来做错误处理。这是因为在这种情况下,如果我们用return来结束该函数,返回任何数字都不是正确的。关于无效输入时的函数如何返回错误信息并结束,本博客第17有更详细的讨论,可以参考。

分享到:
评论

相关推荐

    求旋转数组的最小数字(java实现)

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

    【剑指offer】面试题11-旋转数组的最小数字-完整的可执行代码(Java)

    输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。 解题思路参考博客

    BURmoon#CPP_notes#[数组]旋转数组的最小数字1

    题目把一个数组最开始的若干个元素搬到数组的末尾,称之为数组的旋转输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素NOTE:给出的所有元素都大于0,若数

    旋转数组的最小数字1

    旋转数组的最小数字一把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。例如,数组 [3,4,5,1,2] 为[1,2,3,4,5] 的一个旋转,

    C++中求旋转数组中的最小数字(经典面试题)

    输入一个递增数组的旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1. 算法: (1)当输入的旋转数组非法时:处理! (2)当输入的旋转数组正常时,index1 = 0;...

    剑指Offer(Python多种思路实现):旋转数组的最小数字

    输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0 解题思路一:二分查找 ...

    MangoDowner#clear-leetcode#找出旋转数组的最小元素1

    则此时无法区分最小值是在数组的左半部分还是右半部分(例如:{2,2,2,2,1,2},{2,1,2,2,2,2,2})在这种情况下,只能分别在数组的左右两部分找

    fengmin0722#algorithms-1#面试题11. 旋转数组的最小数字1

    面试题11. 旋转数组的最小数字把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5]

    xdxTao#LeetCode#剑指 Offer 11. 旋转数组的最小数字1

    题目位置题解* 思路* 1、找到数组中元素最小的元素public int minArray(int[] numbers) {

    求解旋转数组的最小数字

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

    剑指offer之 旋转数组的最小数字

    输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。 概念回顾 二分法 ...

    菜鸡的算法修炼——有序数组的二分查找(剑指offer题目,旋转数组的最小值,Java实现)

    输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 又例如{1,0,1,1,1}和{1,1,1,0,1}都可以看成是递增排序数组{0,1,1,1,1}的...

    C语言输出旋转后数组中的最小数元素的算法原理与实例

    输入一个排好序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3, 4, 5, 1, 2}为{1, 2, 3, 4, 5}的一个旋转,该数组的最小值为1。  思路:这道题最直观的解法并不难。从头到尾遍历数组一次,就能找出最小的...

    Java常用ArrayUtile工具类

    查找数组中的最小元素 对数组进行排序 计算数组的中位数 计算数组的众数 计算数组的平均值 判断数组是否为严格递增 计算二维数组中所有元素的和 旋转二维数组90度 寻找目标数组是否为原数组的子集

    php实现有序数组旋转后寻找最小值方法

    输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。 1、利用二分法寻找数组...

    Python算法题源代码-LeetCode(力扣)-寻找旋转排序数组中的最小值

    请你找出并返回数组中的 最小元素 。 你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。 示例 1: 输入:nums = [3,4,5,1,2] 输出:1 解释:原数组为 [1,2,3,4,5] ,旋转 3 次得到输入数组。

    程序员面试题精选100例.doc

    1 数组 3 1.1 求子数组的最大和 3 1.2 查找最小的k个元素 4 1.3 调整数组顺序使奇数位于偶数前面 5 1.4 找出数组中两个只出现一次...1.6 旋转数组的最小元素 11 1.7 扑克牌的顺子 13 2 树 15 2.1 二叉树的非递归操作 15

    leetcode数组中元素出现次数-Interview-Prepration:包含重要问题和面试概念的存储库

    相等数组元素的最小移动量 II 子阵列总和等于 K 回文子串 链表循环 链表中间 链表周期 II 有效的括号字符串 使用队列实现堆栈 使用栈实现队列 滑动窗口最大值 设计循环队列 NQueens 数独解算器 最大元素(滑动窗口)...

    leetcode答案-hello-algo:算法训练,ContinueFighting

    leetcode 答案 Hello algo * Array 找出数组中重复的数字() 找出数组中重复的数字。...输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,

    leetcode中国-LeetCode:由Python和Go实现的LeetCode练习

    搜索旋转数组中的最小值I 搜索旋转数组中的最小值II 搜索旋转数组I 搜索旋转数组II 数组 双指针 颜色分类(荷兰国旗问题) 四数之和 移除元素 数组操作 旋转图片 旋转数组 滑动窗口 无重复字符最长子串 树 验证二叉...

Global site tag (gtag.js) - Google Analytics