剑指offer之面试题8:旋转数组的最小数字
来源:互联网 发布:mysql create trigger 编辑:程序博客网 时间:2024/06/05 16:05
题目描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减序列的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
思路:直接从头到尾遍历数组一次,即可
public int minNumberInRotateArray(int [] array) { if(array==null||array.length<=0) return 0; int min=0; for(int i=1;i<array.length;i++){ if(array[i]<array[min]){ min=i; } } return array[min]; }
但这样的话就没有利用输入的数组本身的特性,时间效率为O(n),还可以更优吗?达不到面试官的肯定
数组旋转以后,分为两个排序的子数组,既然是排序的,可以用二分查找的思想吗?
答案是可以的,分析一下,旋转之后,前面的子数组的元素都大于或等于后面的子数组元素,最小的元素恰好是两个数组的分界线。用两个指针分别指向数组的第一个元素和最后一个元素。第一个元素大于或等于最后一个元素(不完全对,后面会讨论)
取中间的元素,与两个指针指向的元素分别比较,如果大于或等于前面指针指向的元素,则说明中间的元素位于前面的子数组,最小的元素位于中间元素后面,可以将第一个指针指向该中间元素,从而缩小范围,此时第一个指针仍然指向前面的子数组;如果小于或等于后面指针指向的元素,则位于后面的子数组,此时最小元素应位于该元素前面,将第二个指针指向该元素,此时第二个指针仍然指向后面的子数组。
递归,最终第一个指针指向的是前面子数组的最后一个元素,第二个指针指向的是后面子数组的第一个元素(也是最小元素)。结束。
基于以上思路,可以写出如下代码:
public static int minNumberInRotateArray(int [] array) { if(array==null||array.length<=0) return 0; int index1=0; int index2=array.length-1; int indexMiddle=index1; while(array[index1]>=array[index2]){ //定义出口 if(index2-index1==1){ indexMiddle=index2; break; } indexMiddle=(index1+index2)/2; if(array[index1]<=array[indexMiddle]){ index1=indexMiddle; } else if(array[index2]>=array[indexMiddle]){ index2=indexMiddle; } } return array[indexMiddle]; }
依据旋转数组的定义:把前面若干个元素移到后面,所以前面的元素总是大于或等于后面的元素,但是有个例外:0个元素移到后面,此时最小的元素就是第一个元素,所以可以让minIndex初始化为index1。
如果出现下面这种情况呢?
{0,1,1,1,1}旋转成{1,1,1,0,1}或{1,0,1,1,1},第一种情况中间元素1位于前面的子数组,第二种情况中间元素1位于后面的子数组,不能确定到底位于前面还是后面,此时只能顺序查找。
故完整代码如下,已在牛客网提交成功:
import java.util.ArrayList;public class Solution{ public static int minNumberInRotateArray(int [] array) { if(array==null||array.length<=0) return 0; int index1=0; int index2=array.length-1; int indexMiddle=index1; while(array[index1]>=array[index2]){ //定义出口 if(index2-index1==1){ indexMiddle=index2; break; } indexMiddle=(index1+index2)/2; //{0,1,1,1,1}旋转成{1,1,1,0,1}或{1,0,1,1,1},只能顺序查找 if(array[index1]==array[index2]&&array[index1]==array[indexMiddle]){ return MinInorder(array,index1,index2); } if(array[index1]<=array[indexMiddle]){ index1=indexMiddle; } else if(array[index2]>=array[indexMiddle]){ index2=indexMiddle; } } return array[indexMiddle]; } public static int MinInorder(int[] array,int index1,int index2){ int result=array[index1]; for(int i=index1+1;i<=index2;i++){ if(array[i]<result){ result=array[i]; } } return result; } public static void main(String[] args){ int[] array={3,4,5,1,2}; System.out.println(minNumberInRotateArray(array)); }}
- 《剑指Offer》之面试题旋转数组的最小数字
- 【剑指offer】面试题8:旋转数组的最小数字
- 剑指offer面试题8:旋转数组的最小数字
- 剑指Offer:面试题8 :旋转数组的最小数字
- 《剑指offer》面试题8旋转数组的最小数字
- 《剑指Offer》面试题8:旋转数组的最小数字
- 【剑指offer】 面试题8: 旋转数组的最小数字
- 剑指offer-面试题8:旋转数组的最小数字
- 剑指offer面试题8:旋转数组的最小数字
- 【剑指offer】面试题8:旋转数组的最小数字
- 剑指offer面试题8:旋转数组的最小数字
- 剑指offer--面试题8: 旋转数组的最小数字
- 剑指Offer---面试题8:旋转数组的最小数字
- 剑指offer-面试题8-旋转数组的最小数字
- 剑指offer-面试题8 旋转数组的最小数字
- 剑指offer-面试题8-旋转数组的最小数字
- 剑指offer 面试题8 旋转数组的最小数字
- 剑指offer面试题[8]-旋转数组的最小数字
- 一.MariaDB 与mysql
- Centos7多版本python包不能通用问题
- jdbc
- TCP & UDP
- 替换空格
- 剑指offer之面试题8:旋转数组的最小数字
- POI之Excel单元格合并边框问题
- HDU 5665 Lucky(思维题)【BC】
- 【hdu2087】剪花布条——KMP
- C++实现内存复制函数(memmove解决内存重叠)
- operator关键字(重载操作符)
- Android API Guides---Input Events
- 数据库三大范式的一己之见
- C++之深浅拷贝