本随笔记录来自《剑指offer》第二版
/* * 把一个数组最开始的若干个元素搬到数组的尾部,我们称之为 * 数组的旋转。输入一个递增排序的数组的旋转,输入旋转数组的 * 最小元素。例如,数组{3,4,5,1,2}为{1,2,3,4,5}的 * 一个旋转,该数组的最小值为1. */ /* * 暴力搜索法:遍历全部的元素,找出最小值。 */ /* * 二分查找法: * (1)先比较第一个元素和最后一个元素,正常应该是>=的,如果<则证明第一个 * 元素就是最小元素。 * (2)如果第一个元素不是最小元素,取数组中间的元素,比较中间元素与头元素的大小, * 如果中间元素<=头元素,那么代表中间元素与尾元素之间都是递增 * 的,这个时候只取头元素到中间元素,闭区间。再次进行递归。如果 * 中间元素>=头元素,证明头元素与中间元素中间是递增的,最小元素在中间 * 元素和尾元素之间,取中间元素到尾元素,闭区间。再次进行递归。 */ #include<iostream> using namespace std; int Min(int* numbers, int length) { if (numbers == nullptr || length <= 0) { throw new 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 { index2 = indexMid; } } return numbers[indexMid]; } /* * 上面的代码还不能适配以下的情况: * 初始数组为{0,1,1,1,1},旋转之后的数组为 * {1,0,1,1,1}.那么根据我们的代码,最后最小值会取得1. * 那这种情况对应中间元素 = 头元素 = 尾元素,只能是暴力搜索了。 */ #include<iostream> using namespace std; int MinInOrder(int* numbers, int index1, int index2) { int result = numbers[index1]; for (int i = index1 + 1; i <= index2; ++i) { if (numbers[i] < result) { result = numbers[i]; } } return result; } int Min(int* numbers, int length) { if (numbers == nullptr || length <= 0) { throw new 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[index1] == numbers[index2]) && (numbers[index1] == numbers[indexMid])) { return MinInOrder(numbers, index1, index2); } if (numbers[indexMid] >= numbers[index1]) { index1 = indexMid; } else { index2 = indexMid; } } return numbers[indexMid]; }