[经典面试题]输入一个排好序的数组的一个旋转,输出旋转数组的最小元素。

【题目】

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个排好序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3, 4, 5, 1, 2}为{1, 2, 3, 4, 5}的一个旋转,该数组的最小值为1。

【分析】

这道题最直观的解法并不难。从头到尾遍历数组一次,就能找出最小的元素,时间复杂度显然是O(N)。但这个思路没有利用输入数组的特性,我们应该能找到更好的解法。

我们注意到旋转之后的数组实际上可以划分为两个排序的子数组,而且前面的子数组的元素都大于或者等于后面子数组的元素。我们还可以注意到最小的元素刚好是这两个子数组的分界线。我们试着用二元查找法的思路在寻找这个最小的元素。

我们得到处在数组中间的元素。如果该中间元素位于前面的递增子数组,那么它应该大于或者等于第一个指针指向的元素。此时数组中最小的元素应该位于该中间元素的后面。我们可以把第一指针指向该中间元素,这样可以缩小寻找的范围。同样,如果中间元素位于后面的递增子数组,那么它应该小于或者等于第二个指针指向的元素。此时该数组中最小的元素应该位于该中间元素的前面。我们可以把第二个指针指向该中间元素,这样同样可以缩小寻找的范围。我们接着再用更新之后的两个指针,去得到和比较新的中间元素,循环下去。

【代码】

/*********************************
*   日期:2015-01-04
*   作者:SJF0115
*   题目: 输入一个排好序的数组的一个旋转,输出旋转数组的最小元素
*   博客:
**********************************/
#include <iostream>
using namespace std;

int SearchMin(int A[],int n){
    if(n <= 0){
        return -1;
    }//if
    int start = 0,end = n-1;
    // 数组有序
    if(A[end] > A[start]){
        return A[start];
    }//if
    // 数组旋转
    // 二分查找
    while(start <= end){
        int mid = (start + end) / 2;
        // [start,mid]有序[mid,end]无序
        if(A[mid] > A[start]){
            start = mid;
        }
        // [start,mid]无序[mid,end]有序
        else if(A[mid] < A[start]){
            end = mid;
        }
        else{
            return A[mid+1];
        }
    }//while
}

int main(){
    int A[] = {2,3,4,5,6,7,8};
    cout<<SearchMin(A,7)<<endl;
    return 0;
}
时间: 2024-10-10 04:35:41

[经典面试题]输入一个排好序的数组的一个旋转,输出旋转数组的最小元素。的相关文章

python面试题之--打乱排好序的list

例如: >>> a = range(10) >>> a [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> import random >>> random.shuffle(a) >>> a [7, 8, 9, 4, 6, 2, 0, 1, 3, 5] random.shuffle的函数原型为:random.shuffle(x[, random]),用于将一个列表中的元素打乱

一个排好序的数组,找出两数之和为m的所有组合

public static void getGroup(int sum, int arr[]){ if(arr.length<=0) { System.out.println("数组为空"); return; } int start = 0; int end =arr.length-1; while (start <end){ if(arr[start]+arr[end]== sum){ System.out.println("符合要求"+arr[sta

一个排好序的数组,找出两数之和为x的所有组合【双指针】

#include <bits/stdc++.h> using namespace std; const int N = 1e6,INF = 0x3f3f3f3f; int a[N]; int n,x; void fun(int n) { int left = 0, right = n-1; while(left < right) { int ans=a[left] + a[right]; if(ans == x) { cout<<a[left]<<' '<&

【LeetCode-面试算法经典-Java实现】【034-Search for a Range(搜索一个范围)】

[034-Search for a Range(搜索一个范围)] [LeetCode-面试算法经典-Java实现][所有题目目录索引] 原题 Given a sorted array of integers, find the starting and ending position of a given target value. Your algorithm's runtime complexity must be in the order of O(log n). If the targe

[算法]在行列都排好序的矩阵中找数

题目: 给定一个有N*M的整型矩阵matrix和一个整数K,matrix的每一行和每一列都是排好序的.实现一个函数,判断K是否在matrix中. 例如: 0   1   2   5 2   3   4   7 4   4   4   8 5   7   7   9 如果K为7,返回true:如果K为6,返回false. 要求时间复杂度为O(N+M),额外空间复杂度为O(1). 思路: 1.从矩阵最右上角的数开始寻找(row=0,col=M-1). 2.比较当前数matrix[row][col]与

58.有一个已经排好序的数组。现输入一个数,要求按原来的规律将它插入数组中

#include<iostream> using namespace std; int main() { int n,k; int temp; int a[11]={1,4,6,9,11,13,35,44,46,50}; cout<<"原数组是:"<<endl; for(int p=0;p<10;p++) { cout<<a[p]<<" "; } cout<<endl; cout<&

有一个从小到大排好序的数组。现输入一个数,要求按原来的规律将它插入数组中。

<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title></title> <script type="text/javascript"> //有一个从小到大排好序的数组.现输入一个数,要求按原来的规律将它插入数组中. var arr = [1, 2, 3, 4, 5, 7, 9]; function insertScot

【LeetCode-面试算法经典-Java实现】【021-Merge Two Sorted Lists(合并两个排好序的单链表)】

[021-Merge Two Sorted Lists(合并两个排好序的单链表)] [LeetCode-面试算法经典-Java实现][所有题目目录索引] 原题 Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists. 题目大意 合并两个排序链表并返回一个新的列表.新的链表的

将两个排好序的数组,合并到另外一个数组中,并且合并之后的数组也是有序的。

int a[3] = {12, 15, 17}; int b[4] = { 2, 8, 16, 22}; int c[7] = {0}; int i = 0, j = 0, k = 0; while (i < 3 && j < 4 ) { if (a[i] > b[j]) { c[k++] = b[j++]; } else { c[k++] = a[i++]; } } while (i < 3) { c[k++] = a[i++]; } while (j <