(剑指Offer)面试题8:旋转数组的最小数字

题目:

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。

输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。

例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。

思路:

1、遍历数组,找到数组的最小值,时间复杂度O(n);

2、二分查找,时间复杂度O(logn)

注意旋转数组的循环不变量,A[left]>=A[right](这道题的数组为非递减数组,并非严格的递增数组)

特例:无旋转情况以及{0,1,1,1,1,1}旋转数组

查找过程:

旋转数组可以看成两个递增(非减)数组,通过前后两个指针left,right分别指向数组的首尾,

当满足循环不变量时A[left]>=A[right],mid=(left+right)/2,

如果A[mid]>=A[left],说明最小值存在mid后面部分,left=mid;

如果A[mid]>=A[right],说明最小值存在mid前面部分,right=mid;

经过循环之后,最终left会指向第一个递增数组的最后一个数,right会指向第二个递增数组的第一个数,即最小值mid=right。

最终return A[mid];

解决特例问题:

  • 无旋转数组:数组就是递增的,返回第一个数,即A[left],因此mid=left即可;
  • {0,1,1,1,1,1}类似旋转数组:不满足上述查找过程,只能遍历数组。

代码:

#include <iostream>
#include <vector>

using namespace std;

int MinInOrder(int* arr,int left,int right){
    int result=arr[left];
    for(int i=left+1;i<=right;i++){
        if(result>arr[i])
            result=arr[i];
    }
    return result;
}

int Min(int* numbers,int length){
    if(numbers==NULL || length<=0)
        return -1;
    int left=0;
    int right=length-1;
    int mid=left;
    while(numbers[left]>=numbers[right]){
        if(right-left==1){
            mid=right;
            break;
        }
        mid=left+((right-left)>>1);
        if(numbers[left]==numbers[right] && numbers[left]==numbers[mid])
            return MinInOrder(numbers,left,right);
        if(numbers[mid]>=numbers[left])
            left=mid;
        else
            right=mid;
    }
    return numbers[mid];
}

int main()
{
    int A[]={1,0,1,1,1,1,1,1};
    int len=sizeof(A)/sizeof(A[0]);
    Solution s;
    vector<int> nums(A,A+len);
    cout<<s.minNumberInRotateArray(nums)<<endl;
    cout<<Min(A,len)<<endl;
    return 0;
}

在线测试OJ:

http://www.nowcoder.com/books/coding-interviews/9f3231a991af4f55b95579b44b7a01ba?rp=1

AC代码:

class Solution {
public:
	int minNumberInRotateArray(vector<int> rotateArray) {
		int len=rotateArray.size();
        if(len==0)
            return 0;
        int left=0;
        int right=len-1;
        int mid=left;
        //if(rotateArray[left]<rotateArray[right]);
        //	return rotateArray[left];
        while(rotateArray[left]>=rotateArray[right]){
            if(right-left==1){
                mid=right;
                break;
            }
            mid=left+((right-left)>>1);
            if(rotateArray[left]==rotateArray[right] && rotateArray[left]==rotateArray[mid])
                return MinInOrder(rotateArray,left,right);
            if(rotateArray[mid]>=rotateArray[left])
                left=mid;
            else
                right=mid;
        }
        return rotateArray[mid];
	}

	int MinInOrder(const vector<int> &arr,int left,int right){
        int result=arr[left];
        for(int i=left+1;i<=right;i++){
            if(result>arr[i])
                result=arr[i];
        }
        return result;
	}
};

  

时间: 2024-08-29 04:03:02

(剑指Offer)面试题8:旋转数组的最小数字的相关文章

剑指offer面试题8——旋转数组的最小数字

题目1386:旋转数组的最小数字 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:6708 解决:1505 题目描述: 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1. 输入: 输入可能包含多个测试样例,对于每个测试案例, 输入的第一行为一个整数n(1<= n<=1000000):代表旋转数组的元素个数. 输入的第二行包括n

《剑指Offer》算法题——“旋转数组”的最小数字

题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个非递减序列的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1. //这里说的非递减并不是乱序的,也是递增的,只不过递增的过程中可以有相同数字而已 #include <iostream> #include <vector> using namespace std; class Solution { public: int minNu

剑指offer(6)旋转数组的最小数字

题目描述: 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1. NOTE:给出的所有元素都大于0,若数组大小为0,请返回0. 解题代码: function minNumberInRotateArray(rotateArray) { // write code here if(rotateArray.length == 0){ retu

剑指offer 面试题33 把数组排成最小的数

题目链接: 剑指offer 题目链接: 把数组排成最小的数, 例如{3, 32, 321} 输出: 321323 解题思路: 我现在已经知道正确答案了, 就是没有办法去证明, 先去开会, 在开会的时候再去想. 代码: #include <iostream> #include <cstdio> #include <string> #include <vector> #include <cstring> #include <iterator&g

剑指offer 面试题33—把数组排成最小的数

题目: 输入一个正整数数组,把数组里面的所有数字连接起来排成一个数,打印能拼接出的所有数字中最小的一个.例如输入数组{3, 32,  321},则打印这三个数字能排成的最小数字321323. 基本思想:O(nlogn) 两个数字m和n能拼接数字mn和nm.如果mn<nm,那么我们应该打印出mn,也就是m应该排在n的前面,我们定义此时m小于n:反之,如果nm<mn,我们定义n小于m.如果mn=nm,m等于n. 如对321和32,排序为32132<32321,所以321<32(这个小于

【剑指offer】面试题 11. 旋转数组的最小数字

面试题 11. 旋转数组的最小数字 题目描述 题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非递减排序的数组的一个旋转, 输出旋转数组的最小元素. 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1. NOTE:给出的所有元素都大于0,若数组大小为0,请返回0. 解答 复杂度:O(logN) + O(1) public class Solution { public int minNumberInRotateArray(int

剑指Offer 面试题36:数组中的逆序对及其变形(Leetcode 315. Count of Smaller Numbers After Self)题解

剑指Offer 面试题36:数组中的逆序对 题目:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.输入一个数组,求出这个数组中的逆序对的总数. 例如, 在数组{7,5,6,4}中,一共存在5个逆序对,分别是(7,6),(7,5),(7,4),(6,4)和(5,4),输出5. 提交网址: http://www.nowcoder.com/practice/96bd6684e04a44eb80e6a68efc0ec6c5?tpId=13&tqId=11188 或 htt

剑指offer面试题29:数组中出现次数超过一半的数字

题目:数组中有一个数字出现的次数超过数组长度的一般,请找出这个数字,例如输入一个长度为9的数组(1,2,3,2,2,2,5,4,2,).由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2. 个人第一眼想法是通过一个sort函数,再判断中间那数出现次数,只要出现多于n/2,就直接输出. 一般来说,最为直观的算法面试官都不会满意,那么有没有更优的算法呢? 这种算法是受快速排序算法的启发.在随机快速排序算法中,我们现在数组中随机选择一个数字,然后调整数组中数字的顺序,使得比选中的数字小的数字

【剑指Offer学习】【面试题8 : 旋转数组的最小数字】

题目: 把一个数组最开始的若干个元素搬到数组的末尾, 我们称之数组的旋转.输入一个递增排序的数组的一个旋转, 输出旋转数组的最小元素.例如数组{3,4, 5, 1, 2 }为{ l1,2,3, 4,5}的一个旋转,该数组的最小值为1 实现代码如下: public class Test08 { /** * 把一个数组最开始的若干个元素搬到数组的末尾, 我们称之数组的旋转. * 输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素. * 例如数组{3, 4, 5, 1, 2}为{l ,2, 3,

面试题08_旋转数组的最小数字——剑指offer系列

题目描述: 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素. 例如:数组{3, 4, 5, 1 , 2} 是 数组{1,2,3,4,5}的一个旋转,该数组最小的数是1. 我们要做的就是找到这个旋转后数组的最小数. 解题思路: 思路1:直接遍历数组,找到最小的数,简单粗暴,时间复杂度O(n),空间复杂度O(1). 一般情况下,能够做到思路一的时空复杂度就很好了,但是这个题目,还可以有更好的思路,将时间复杂度降低. 思路2: