剑指offer系列(7)——旋转数组的最小数字
2017-12-18 13:11
190 查看
题目要求如下:
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
这个题的突破口是要发现一个这种排序数组的一个特点:即旋转将数组分成了两个部分的小数组,而后面这个小数组的每个值小于前面的小数组(这里不考虑特殊情况,默认为排序好的递增数组,且其中元素不重复,重复的在后面讨论)
当处于这种情况时,我们只需利用上面的这个特点,即最小得值一定在第二个数组中且一定小于第一个数组中的最小值(第一个数组中最小值为第一个值,eg:[3,4,5,1,2]中的3),这个时候我们可以采用类似二分查找的方法。令一个first下标遍历指针,在令一个final下标遍历指针,这两个指针分别指向第一个元素和最后一个元素,根据其中间值的大小不断缩小范围直至找到。伪代码如下:
下面我们分析特殊情况,当这个数组中有重复值时,并且导致了middle和indexfirst相等。
这里也要分为两种情况:
1) 若first和final之间是全为某一个数的特殊情况,这是,我们只能进行循环遍历。
2) 若first值与中间值相同,但与final值不同,如[5,5,5,1,1],此时我们的算法仍旧可以处理这种情况。所以,这种情况并不用考虑。
综上,我们可以写出代码:
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
这个题的突破口是要发现一个这种排序数组的一个特点:即旋转将数组分成了两个部分的小数组,而后面这个小数组的每个值小于前面的小数组(这里不考虑特殊情况,默认为排序好的递增数组,且其中元素不重复,重复的在后面讨论)
当处于这种情况时,我们只需利用上面的这个特点,即最小得值一定在第二个数组中且一定小于第一个数组中的最小值(第一个数组中最小值为第一个值,eg:[3,4,5,1,2]中的3),这个时候我们可以采用类似二分查找的方法。令一个first下标遍历指针,在令一个final下标遍历指针,这两个指针分别指向第一个元素和最后一个元素,根据其中间值的大小不断缩小范围直至找到。伪代码如下:
If(middle > indexfirst) first = middle; else if(middle < indexfirst) final = middle; else 特殊情况
下面我们分析特殊情况,当这个数组中有重复值时,并且导致了middle和indexfirst相等。
这里也要分为两种情况:
1) 若first和final之间是全为某一个数的特殊情况,这是,我们只能进行循环遍历。
2) 若first值与中间值相同,但与final值不同,如[5,5,5,1,1],此时我们的算法仍旧可以处理这种情况。所以,这种情况并不用考虑。
综上,我们可以写出代码:
package com.offer; public class MinNumberInRotatedArray { /* * 旋转数组找最小值 * * 注意!只有低位高位中间位三者完全一样时才采用遍历寻找 ,防止 5,5,5,1,2 ,所以要把特殊情况放在前面 */ public static void main(String[] args) { int[] a = new int[]{4,5,1,2,3}; System.out.println(findMinNumber(a)); } public static int findMinNumber(int[] array){ if (array == null || array.length <= 0) { throw new RuntimeException("数组为空或长度小于等于零"); } int low = 0; //低位遍历指针 int high = array.length - 1; //高位遍历指针 if (array.length == 1) { //只有一个元素 return array[0]; } int result = 0; //最小值 while(Math.abs(high - low) != 1){ if (array[low] == array[high] && array[high] == array[(low + high) >> 1]) { //中间值与低位元素与高位元素相等,无法判断,必须遍历查询 for (int i = 0; i < array.length; i++) { result = result > array[i] ? array[i] : result; } break; //跳出while循环 否则将无限执行下去 ! }else if(array[(low + high) >> 1] < array[low]){ //以最小值为界,中间值在后面 high = (low + high) >> 1; }else{ //以最小值为界 ,中间值在前面 low = (low + high) >> 1; } } result = array[high]; return result; } }
相关文章推荐
- 剑指Offer系列---(11)旋转数组的最小数字
- 面试题08_旋转数组的最小数字——剑指offer系列
- 剑指offer系列-T8旋转数组的最小数字
- 剑指Offer系列-面试题8:旋转数组的最小数字
- 剑指offer系列之六:旋转数组的最小值
- 《剑指Offer》之面试题旋转数组的最小数字
- 旋转数组的最小数字(剑指offer)
- JAVA实现旋转数组的最小数字问题(《剑指offer》)
- 剑指offer(九)之旋转数组的最小数字
- 牛客《剑指Offer》 旋转数组的最小数字
- 《剑指offer》-旋转数组的最小数字
- (剑指Offer)面试题8:旋转数组的最小数字
- 《剑指offer》旋转数组的最小数字
- [置顶] 剑指offer:第8题旋转数组的最小数字
- 剑指Offer - 九度1386 - 旋转数组的最小数字
- (未完成)《剑指offer》(面试题8):旋转数组的最小数字
- 《剑指Offer》学习笔记--面试题8:旋转数组的最小数字
- 《剑指offer》---旋转数组中的最小数字 和 斐波那契数列
- 《剑指offer》:[11]旋转数组的最小数字
- (剑指offer)旋转数组的最小数字