旋转数组的最小数字 python
来源:互联网 发布:央视索福瑞收视数据 编辑:程序博客网 时间:2024/06/10 09:39
题目描述
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
1.如果发生旋转,前面的数至少去了一个放在数组的后面;
1)旋转后,数组分为两个排序数组,而且前一个数组中的数均大于等于后一个数组中的数,因为要查找数组中的最小数,也就是第二个数组中的第一个数,可以采用二分查找的思想;
2)设置两个指针p1,p2,p1指向数组的开始位置,也就是第一个数组的开始位置,p2指向数组的终止位置,也就是第二个数组的结束位置。Mid=p1+p2/2;
如果中间位置mid的数大于p1指向的数,则mid在第一个数组中,让p1指向mid所指向的数,p1指向的依然是数组1的数;
如果中间位置mid的数小于p2所指向的位置,则mid在第二个数组中,p2指向mid指向的数,p2指向的依然是数组2的数;
Mid不是指向数组1的数,就是指向数组2的数,指向数组1的数,就让p1移动到mid的位置,指向数组2就让p2数组移动到mid的位置;直到p2移动到数组1的结束的位置,p1移动到数组2的开始的位置,此时p2与p1挨着,而且p1所指向的数组2的起始位置中存放的就是最小数;
2.如果中间位置的数既等于p1位置数,又等于p2位置的数,这时候,不能确定移哪个指针,就必须采用顺序查找的方法来寻找最小数;
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小元素为1.
我们注意到旋转之后的数组实际上可以划分为两个排序的子数组,而且前面的子数组的元素都是大于或者等于后面子数组的元素。我们还注意到最小的元素刚好是这两个子数组的分界线。在排序的数组中我们可以利用二分查找来实现O(logn)的查找。本题给出的数组在一定程度上是排序的,因此我们可以试着用二分查找的思路来寻找这个最小的元素。
以前面的例子为例,我们先把第一个指针指向第0个元素,把第二个指针指向第4个元素,如图所示。位于两个指针中间(在数组的下标是2)的数字是5,它大于第一个指针指向的数字。因此中间数字5一定位于第一个递增字数组中,并且最小的数字一定位于它的后面。因此我们可以移动第一个指针让它指向数组的中间。
此时位于这两个指针中间的数字为1,它小于第二个指针指向的数字。因此这个中间数字为1一定位于第二个递增子数组中,并且最小的数字一定位于它的前面或者它自己就是最小的数字。因此我们可以移动第二个指针指向两个指针中间的元素即下标为3的元素。
此时两个指针的距离为1,表明第一个指针已经指向了第一个递增子数组的末尾,而第二个指针指向第二个递增子数组的开头。第二个子数组的第一个数字就是最小的数字,因此第二个指针指向的数字就是我们查找的结果。
上述方法是否就一定够完美了呢?面试官会告诉你其实不然。他将提示我们再仔细分析小标leftIndex和rightIndex分别和途中P1和P2相对应)的两个数相同的情况。在前面,当着两个数相同,并且它们中间的数相同的也相同时,我们把IndexMid赋给了leftIndex,也就是认为此时最小的数字位于中间数字的后面。是不是一定一样?
我们再来看一个例子。数组{1,0,1,1,1}和数组{1,1,1,0,1}都可以堪称递增排序数组{0,1,1,1,1}的旋转,图2分别画出它们由最小数字分隔开的两个子数组。
这两种情况中,第一个指针和第二个指针指向的数字都是1,并且两个指针中间的数字也是1,这3个数字相同。在第一种情况中,中间数字(下标为2)位于后面是子数组;在第二种情况中,中间数字(下标为2)位于前面的子数组中。因此,当两个指针指向的数字及它们中间的数字三者相同的时候,我们无法判断中间的数字是位于前面的子数组中还是后面的子数组中国,也无法移动两个指针来缩小查找的范围。此时,我们不得不采用顺序查找的方法。
总结:此题就是利用两个指针,一个往后移,一个往前移,具体怎么移,通过mid的大小控制;直到两个指针的位置挨着,就可以找到最小数了!
还需要考虑:
# -*- coding: utf-8 -*-""" 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。 思路:首先所给的旋转数组书局部有序的,这完全可以想到使用二分查找来解决会优化线性查找的性能。这道题的解法和二分查找类似,设置三个指针,left,right,mid。当mid>=left时说明最小数在右边,当mid<=right时说明在左边。但是在left==right==mid时就不能判断了,只能顺序查找。边界情况需要特殊处理。"""def minNumberInRotateArray(rotateArray): left = 0 #左侧的指针 right = len(rotateArray) - 1 #右侧的指针 mid = 0 #中间的指针 while rotateArray[left] >= rotateArray[right]: #当两个指针走到挨着的位置时,即right - left == 1,right就是最小数了 if right - left == 1: mid = right break mid = left + (int)((right-left)/2) #如果中间位置的数既等于left位置的数又等于right位置的数 if rotateArray[left] == rotateArray[mid] and rotateArray[right]==rotateArray[mid]: return minInorder(rotateArray,left,right) #若中间位置的数大于左边位置的数,说明最小的数在mid位置的右边中,让left走到mid的位置 if rotateArray[mid] >= rotateArray[left]: left = mid #若中间位置的数小于右边指针位置的数,说明最小的数在mid位置的左边,让right走到mid的位置 elif rotateArray[mid] < rotateArray[right]: right = mid return rotateArray[mid]#顺序查找数组里的最小值def minInorder(rotateArray,left,right): minNum = rotateArray[left] length = right - left for i in range(length): if rotateArray[left+i] < minNum: minNum = rotateArray[left+i] return minNumif __name__ == "__main__": array = [5,6,7,8,3,4] print minNumberInRotateArray(array)
- 旋转数组的最小数字 python
- python--c++--旋转数组的最小数字
- Python:旋转数组的最小数字
- 旋转数组的最小数字
- 旋转数组的最小数字
- 旋转数组的最小数字
- 旋转数组的最小数字
- 旋转数组的最小数字
- 旋转数组的最小数字
- 旋转数组的最小数字
- 旋转数组的最小数字
- 旋转数组的最小数字
- 旋转数组的最小数字
- 旋转数组的最小数字
- 旋转数组的最小数字
- 旋转数组的最小数字
- 旋转数组的最小数字
- 旋转数组的最小数字
- 【Boost】boost库asio详解5——resolver与endpoint使用说明
- enote笔记语言(3)(ver0.2)
- bzoj 4032: [HEOI2015]最短不公共子串 (DP+后缀自动机)
- task_struct结构
- 关于Spring mvc框架的工作原理或即工作流程。
- 旋转数组的最小数字 python
- bzoj1008: [HNOI2008]越狱
- 牛刀 —— 汨罗网络屏幕投影软件的技术实现
- LeetCode:triangle
- Understand-4.0.877-Linux-64bit.tgz最新版本2017年源代码阅读利器,养眼theme之配置
- 基础练习 龟兔赛跑预测
- Mac 快速安装 Ubuntu 虚拟机
- LBSN2016 关注热点
- 最小二乘法介绍