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

面试题8:旋转数组的最小数字

题目:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个已从小到大排好序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,
4, 5, 1, 2}为{1, 2, 3, 4, 5}的一个旋转,该数组的最小值为1。(要求不能直接遍历数组来求解.)

提交网址: http://www.nowcoder.com/practice/9f3231a991af4f55b95579b44b7a01ba?tpId=13&tqId=11159

或 http://ac.jobdu.com/problem.php?pid=1386

时间限制:1 秒  内存限制:32 M 特殊判题:否  提交:7633
 解决:1686

题目描述:

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

输入:

输入可能包含多个测试样例,对于每个测试案例,

输入的第一行为一个整数n(1<= n<=1000000):代表旋转数组的元素个数。

输入的第二行包括n个整数,其中每个整数a的范围是(1<=a<=10000000)。

输出:

对应每个测试案例,

输出旋转数组中最小的元素。

牛客网OJ 样例输入:(对于C++提交:vector<int> rotateArray)
3 4 5 1 2
九度OJ 样例输入:
5
3 4 5 1 2
样例输出:
1

分析:

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

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

牛客网OJ AC代码:

#include<cstdio>
#include<vector>
using namespace std;
class Solution {
public:
    int minNumberInRotateArray(vector<int> rotateArray)
	{
        if(rotateArray.size() == 0) return 0;  // 输入的是空数组
        int low = 0, high = rotateArray.size() - 1;
        int mid;
		if(rotateArray[low] < rotateArray[high]) return rotateArray[low];   // 输入的是完全旋转数组
        while(rotateArray[low] >= rotateArray[high])  // 输入的是部分旋转数组
		{
            mid =(low + high) / 2;
            if(high - low == 1) return rotateArray[high];
            // 当low和high两个指针相邻时候,就找到了最小值,也就是右边序列的第一个值
            if(rotateArray[low] == rotateArray[mid] && rotateArray[mid] == rotateArray[high])
			{   // 当rotateArray[low]、rotateArray[high]、rotateArray[mid]三者相等时,
                // 无法确定中间元素是属于前面还是后面的递增子数组,只能顺序查找
                int min = rotateArray[low];
                for(int i = low + 1; i <= high; i++)
                    min = rotateArray[i]<min ? rotateArray[i] : min;
                return min;
            }
            if(rotateArray[low] <= rotateArray[mid]) low = mid;
            // 中间元素位于前面的递增子数组, 且此时最小元素位于中间元素的后面
            else high = mid;
            // 中间元素位于后面的递增子数组, 且时最小元素位于中间元素的前面
        }
        return rotateArray[low];
    }
};
// 以下为测试
int main()
{
	Solution sol;
	vector<int> vec1={3,4,5,1,1,2};
	vector<int> vec2={1,1,2,3,4,6};
	int res1 = sol.minNumberInRotateArray(vec1);
	int res2 = sol.minNumberInRotateArray(vec2);
	printf("%d\n", res1);
	printf("%d\n", res2);
	return 0;
}

按《剑指offer》2014版中的思路写出的代码:

#include <cstdio>
#include <vector>
using namespace std;
class Solution{
public:
    int minNumberInRotateArray(vector<int> rotateArray)
	{
        int size = rotateArray.size(); // 输入的是空数组
        if(size == 0) return 0;
        int left = 0, mid = 0, right = size - 1;
		if(rotateArray[left] < rotateArray[right]) return rotateArray[left];   // 输入的是完全旋转数组
        while(rotateArray[left] >= rotateArray[right])  // 输入的是部分旋转数组
		{
            if(right - left == 1) // 分界点
			{
                mid = right;
                break;
            }
            mid = (right + left) / 2;
            if(rotateArray[left] == rotateArray[right] && rotateArray[left] == rotateArray[mid])
			{
            	// 顺序寻找最小值
                int min = rotateArray[left];
                for(int i = left + 1; i <= right; i++)
                    min = rotateArray[i]<min ? rotateArray[i] : min;
                return min;
            }
            // 中间元素位于前面的递增子数组, 且此时最小元素位于中间元素的后面
            if(rotateArray[mid] >= rotateArray[left]) left = mid;
          // 中间元素位于后面的递增子数组, 且时最小元素位于中间元素的前面
            else right = mid;
        }
        return rotateArray[mid];
    }
};
// 以下为测试
int main()
{
	Solution sol;
	vector<int> vec1={3,4,5,1,1,2};
	int res1 = sol.minNumberInRotateArray(vec1);

	printf("%d\n", res1);
	return 0;
}
时间: 2024-10-09 09:27:52

剑指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,