剑指offer面试题8:旋转数组的最小数字
2017-08-22 10:55
531 查看
题目描述:
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转。输出旋转数组的最小元素。例如数组{3,4,5,1,2}是{1,2,3,4,5}的一个旋转,该数组的最小元素为1。思路分析:
1、旋转数组的特点:1)旋转数组可以划分为两个排序的递增子数组,且前面的子数组的元素都大于或者等于后面子数组的元素;
2)最小的元素刚好是两个子数组的分界线。
2、分析:
这个题目最直观的方法是从头到尾遍历数组一次,时间复杂度为O(n),但是这个思路没有利用旋转数组的特性。考虑旋转数组的两个特性,我们可以思考一下排好序的数组的查找算法,可以使用二分查找。
假设数组为a[],用两个指针low, high分别指向数组的第一个元素和最后一个元素,mid指向数组的中间元素。
1)如果 a[mid] > a[low],数组中最小元素应位于 a[mid] 的后面,把low指针指向mid处,缩小寻找范围;
2)如果a[mid] < a[high],数组中最小元素应位于 a[mid]的前面,把high指针指向mid处,缩小寻找范围;
3)最终low指针将指向前面子数组的最后一个元素,high指针将指向后面子数组的第一个元素。此时low和high相邻,high指针刚好指向最小元素。
特例:
1)如果把排序数组前面0个元素搬到最后面,即排序数组本身仍然是数组的一个旋转,此时,数组中第一个元素就是最小元素,可以直接返回。所以代码中一开始把indexMid初始化为index1。
2)数组{1,0,1,1,1}和{1,1,1,0,1}都是{0,1,1,1,1}的旋转数组,它们的中间元素都为1,此时无法判断中间元素是位于前面的子数组还是后面的子数组,只能使用顺序查找。
时间复杂度:
最坏O(n),平均O(log2 n)代码及测试:
#include <iostream> #include <assert.h> using namespace std; int MinUseOrder(int num[], int low, int high); //求旋转数组的最小数字 int Min(int * num, int n) { if(num == NULL || n <= 0) { cout << "Invalid parameters" << endl; return -1; } int low = 0, high = n - 1; int mid = low;//mid初始化为0,确保了当数组旋转了0个元素时算法的正确性 while(num[low] >= num[high]) { if(high - low == 1) { mid = high; break; } mid = (low + high) / 2; if(num[low] == num[mid] && num[mid] == num[high]) return MinUseOrder(num, low, high); //使用顺序查找 if(num[mid] >= num[low]){ low = mid; } else if(num[mid] <= num[high]){ high = mid; } } return num[mid]; } int MinUseOrder(int num[], int low, int high) { int res = num[low]; for(int i = low + 1; i < high; i ++) { if(res > num[i]) res = num[i]; } return res; } void test1() { int num[5] = { 3, 4, 5, 1, 2}; int min = Min(num,5); cout << min << endl; } void test2() { int num[8] = {3, 3, 4, 5, 1, 1, 2, 2}; int min = Min(num, 8); cout << min << endl; } void test3() { //边界值测试:输入为升序数组 int num[5] = {1, 2, 3, 4, 5}; int min = Min(num, 5); cout << min << endl; } void test4() { //边界值测试:输入为只包含一个数字的数组 int num[1] = {1}; int min = Min(num, 1); cout << min << endl; } void test5() {//边界值测试:输入为只包含一个数字的数组 int * num = NULL; int min = Min(num, 1); cout << min << endl; } int main() { test1(); test2(); test3(); test4(); test5(); return 0; }
相关文章推荐
- 剑指offer面试题[8]-旋转数组的最小数字
- 剑指Offer_面试题08_旋转数组的最小数字
- 剑指offer面试题8:旋转数组的最小数字
- 剑指offer-面试题8:旋转数组中的最小数字
- 旋转数组的最小数字(剑指offer面试题)
- 【剑指offer】面试题 11:旋转数组的最小数字
- [剑指offer][面试题08]求旋转数组的最小数字
- 【剑指offer】面试题八:旋转数组的最小数字
- 【剑指offer】面试题8:旋转数组的最小数字
- 【练习笔记】剑指offer-面试题8 :旋转数组的最小数字
- 【剑指Offer】面试题8:旋转数组的最小数字
- 剑指offer——面试题8:旋转数组的最小数字
- 剑指offer之面试题8:旋转数组的最小数字
- 剑指offer-面试题8-旋转数组的最小数字
- 【剑指offer】面试题8:旋转数组中的最小数字
- 剑指offer-面试题8 旋转数组的最小数字
- 剑指offer-chapter2-面试题8-旋转数组的最小数字(java)
- 剑指offer面试题8:旋转数组的最小数字
- 【剑指offer】2.4.1查找和排序——面试题8:旋转数组的最小数字
- 【剑指Offer面试题】 九度OJ1386:旋转数组的最小数字