[剑指offer-11]旋转数组的最小数字
2018-12-03 16:14
357 查看
题目描述:
把一个数组最开始的若干个元素搬到数组的末尾, 我们称之数组的旋转。
输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3, 4, 5, 1, 2}为{l ,2, 3, 4, 5}的一个旋转,该数组的最小值为1。
思路:
用二分法来查找可提高速度,分为三种情况:
- 典型输入
- 单调升序数组,旋转0个元素,也就是单调升序数组本身
- 第一个数字和最后一个数字重复和中间数字重复,二分法无效。采用顺序法。
例如:数组{1,0,1,1,1}和数组{1,1,1,0,1}
代码(java 版):
public class Test11 { /** * 把一个数组最开始的若干个元素搬到数组的末尾, 我们称之数组的旋转。 * 输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。 * 例如数组{3, 4, 5, 1, 2}为{l ,2, 3, 4, 5}的一个旋转,该数组的最小值为 */ public static int getMin(int[] numbers) { if (numbers == null || numbers.length <= 0) { throw new RuntimeException("错误输入"); } //定义开始处理的第一个指针 int index1 = 0; //定义开始处理的第二个指针 int index2 = numbers.length - 1; //设置处理的初始值 int mid = index1; while (numbers[index1] >= numbers[index2]) { //第一个数字总是大于或者等于最后一个数字 //循环结束条件 if (index2 - index1 == 1) { mid = index2; break; } mid = (index1 + index2) / 2; //如果三个数都相等,则二分法无效,需要进行顺序处理,从头到尾找最小的元素 if (numbers[index1] == numbers[index2] && numbers[mid] == numbers[index1]) { return minInorder(numbers, index1, index2); } if (numbers[index1] <= numbers[mid]) { //中间的数字在第一个数组中,我们要找的最小的数字应该在中间数字的后面 index1 = mid; } else if (numbers[mid] <= numbers[index2]) { //最小的元素位于中间数的前面 index2 = mid; } } return numbers[mid]; } /** * 按顺序法找数组中的最小值 * * @param numbers * @param index1 * @param index2 * @return */ public static int minInorder(int[] numbers, int index1, int index2) { int result = numbers[index1]; for (int i = index1 + 1; i <= index2; i++) { if (result >= numbers[i]) { result = numbers[i]; } } return result; } public static void main(String[] args) { // 1.输入NULL // System.out.println(getMin(null)); //2. 典型输入,单调升序的数组的一个旋转 int[] array1 = {3, 4, 5, 1, 2}; System.out.println(getMin(array1)); // 3.有重复数字,但重复的数字不是第一个数字和最后一个数字 int[] array2 = {3, 4, 5, 1, 2, 2}; System.out.println(getMin(array2)); //4. 有重复数字,并且重复的数字刚好的最小的数字 int[] array3 = {3, 4, 5, 1, 1, 2}; System.out.println(getMin(array3)); // 有重复的数字,并且重复的数字刚好是第一个数字和最后一个数字 int[] array4 = {1,0,1,1,1}; System.out.println(getMin(array4)); int[] array5 = {1,1,1,0,1}; System.out.println(getMin(array5)); // 单调升序数组,旋转0个元素,也就是单调升序数组本身 int[] array6 = {1,2,3,4,5,5}; System.out.println(getMin(array6)); // 数组中只有一个数字 int[] array7 = {2}; System.out.println(getMin(array7)); // 数组中数字都相同 int[] array8 = {7,7,7,7,7,7}; System.out.println(getMin(array8)); } }
测试结果
1 1 1 0 0 1 2 7
代码(python 版):
# -*-coding:utf-8-*- class Numbers: def getMax(self,numbers): lenArr = len(numbers) if not numbers or lenArr <= 0: return None index1 = 0 index2 = lenArr-1 mid = index1 while numbers[index1] >= numbers[index2]: if index2-index1 == 1: mid = index2 break mid = (index1+index2)/2 # 如果index1,index2和mid的值相同,改用顺序法查找 if numbers[index1]==numbers[index2] and numbers[index1] == numbers[mid]: return self.getMinOrder(numbers,index1,index2) if numbers[mid] >= numbers[index1]: index1 = mid elif numbers[mid] <= numbers[index2]: index2 = mid return numbers[mid] def getMinOrder(self,list, index1, index2): result = list[index1] for i in xrange(index1+1,index2+1): if result >= list[i]: result = list[i] return result numbers = Numbers(); list = [3,4,5,1,2] print numbers.getMax(list) list2 = [3,4,5,1,2,2] print numbers.getMax(list2) list3 = [3,4,5,1,1,2] print numbers.getMax(list3) list4 = [1,0,1,1,1] print numbers.getMax(list4) list5 = [1,1,1,0,1] print numbers.getMax(list5) list6 = [1,2,3,4,5,5] print numbers.getMax(list6) list7 = [2] print numbers.getMax(list7) list8 = [7,7,7,7,7,7] print numbers.getMax(list8) print numbers.getMax([])
测试结果
1 1 1 0 0 1 2 7None
相关文章推荐
- 剑指offer--面试题11:旋转数组的最小数字
- 【剑指offer】面试题 11:旋转数组的最小数字
- 剑指Offer-11:旋转数组的最小数字
- 【剑指offer】面试题11:旋转数组的最小数字
- 剑指offer:旋转数组的最小数字
- 剑指Offer---面试题8:旋转数组的最小数字
- 旋转数组的最小数字(剑指Offer 第 6 题)
- 剑指offer第六题【旋转数组的最小数字】c++实现
- 剑指Offer——旋转数组的最小数字
- 剑指offer题解C++【6】旋转数组的最小数字
- [牛客网,剑指offer,python] 旋转数组的最小数字
- 剑指Offer旋转数组中的最小数字
- 剑指offer之面试题8:旋转数组的最小数字
- 【剑指offer】旋转递增数组的最小数字
- 剑指offer之五---旋转数组的最小数字
- 剑指offer - 旋转数组的最小数字
- 剑指Offer之旋转数组的最小数字
- 【剑指offer】旋转数组的最小数字
- 剑指 offer set 3 旋转数组的最小数字
- 旋转数组中的最小数字,剑指offer,P70 二分查找来实现O(logn)的查找