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

Solution1:
自己想的复杂度为O(n)O(n)O(n)的算法,若用二分查找则:
1.代码复杂;2.最坏情况下的二分查找的时间复杂度亦为O(n)O(n)O(n)

class Solution {
public:int minNumberInRotateArray(vector<int> rotateArray) {int n=rotateArray.size();if(n<=1) return n==0? 0:rotateArray[0];for(int i=1;i<n;i++){if(rotateArray[i]<rotateArray[i-1])return rotateArray[i];}return rotateArray[0];}
};

Solution2:书中的思路。参考链接:
https://www.nowcoder.com/profile/648947/codeBookDetail?submissionId=2954831
剑指Offer中有这道题目的分析。这是一道二分查找的变形的题目。
旋转之后的数组实际上可以划分成两个有序的子数组:前面子数组的大小都大于后面子数组中的元素
注意到实际上最小的元素就是两个子数组的分界线。本题目给出的数组一定程度上是排序的,因此我们试着用二分查找法寻找这个最小的元素。
思路:
(1)我们用两个指针left,right分别指向数组的第一个元素和最后一个元素。按照题目的旋转的规则,第一个元素应该是大于最后一个元素的(没有重复的元素)。
但是如果不是旋转,第一个元素肯定小于最后一个元素。
(2)找到数组的中间元素。
中间元素大于第一个元素,则中间元素位于前面的递增子数组,此时最小元素位于中间元素的后面。我们可以让第一个指针left指向中间元素。
移动之后,第一个指针仍然位于前面的递增数组中。
中间元素小于第一个元素,则中间元素位于后面的递增子数组,此时最小元素位于中间元素的前面。我们可以让第二个指针right指向中间元素。
移动之后,第二个指针仍然位于后面的递增数组中。
这样可以缩小寻找的范围。
(3)按照以上思路,第一个指针left总是指向前面递增数组的元素,第二个指针right总是指向后面递增的数组元素。
最终第一个指针将指向前面数组的最后一个元素,第二个指针指向后面数组中的第一个元素。
也就是说他们将指向两个相邻的元素,而第二个指针指向的刚好是最小的元素,这就是循环的结束条件。
到目前为止以上思路很耗的解决了没有重复数字的情况,这一道题目添加上了这一要求,有了重复数字。
因此这一道题目比上一道题目多了些特殊情况:
我们看一组例子:{1,0,1,1,1} 和 {1,1, 1,0,1} 都可以看成是递增排序数组{0,1,1,1,1}的旋转。
这种情况下我们无法继续用上一道题目的解法,去解决这道题目。因为在这两个数组中,第一个数字,最后一个数字,中间数字都是1。
第一种情况下,中间数字位于后面的子数组,第二种情况,中间数字位于前面的子数组。
因此当两个指针指向的数字和中间数字相同的时候,我们无法确定中间数字1是属于前面的子数组(绿色表示)还是属于后面的子数组(紫色表示)。
也就无法移动指针来缩小查找的范围。

#include <iostream>
#include <vector>
#include <string>
#include <stack>
#include <algorithm>
using namespace std;class Solution {
public:int minNumberInRotateArray(vector<int> rotateArray) {int size = rotateArray.size();if(size == 0){return 0;}//ifint left = 0,right = size - 1;int mid = 0;// rotateArray[left] >= rotateArray[right] 确保旋转while(rotateArray[left] >= rotateArray[right]){// 分界点if(right - left == 1){mid = right;break;}//ifmid = left + (right - left) / 2;// rotateArray[left] rotateArray[right] rotateArray[mid]三者相等// 无法确定中间元素是属于前面还是后面的递增子数组// 只能顺序查找if(rotateArray[left] == rotateArray[right] && rotateArray[left] == rotateArray[mid]){return MinOrder(rotateArray,left,right);}//if// 中间元素位于前面的递增子数组// 此时最小元素位于中间元素的后面if(rotateArray[mid] >= rotateArray[left]){left = mid;}//if// 中间元素位于后面的递增子数组// 此时最小元素位于中间元素的前面else{right = mid;}//else}//whilereturn rotateArray[mid];}
private:// 顺序寻找最小值int MinOrder(vector<int> &num,int left,int right){int result = num[left];for(int i = left + 1;i < right;++i){if(num[i] < result){result = num[i];}//if}//forreturn result;}
};int main(){Solution s;//vector<int> num = {0,1,2,3,4,5};//vector<int> num = {4,5,6,7,1,2,3};vector<int> num = {2,2,2,2,1,2};int result = s.minNumberInRotateArray(num);// 输出cout<<result<<endl;return 0;
}

剑指offer——面试题8:旋转数组的最小数字相关推荐

  1. 剑指offer面试题[8]-旋转数组的最小数字

    题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个 ...

  2. 剑指Offer - 面试题11. 旋转数组的最小数字(二分查找)

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

  3. 剑指offer面试题11. 旋转数组的最小数字(二分查找)

    题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的 ...

  4. 剑指offer(12)旋转数组的最小数字

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

  5. 剑指offe面试题8 旋转数组的最小数字 (java实现)

    解题思路: 针对旋转数组的特点,即旋转后,数组的前半部分是有序的,后半部分是有序的. 1.先考虑一般情况:可以参考二分查找的思想,在数组中设置两个指针,一个指向数组的起始位置,一个指向数组的结束位置. ...

  6. j剑指offer面试题[33]-把数组排成最小的数

    题目描述 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323. 思路: 可以 ...

  7. 剑指Offer - 面试题45. 把数组排成最小的数(字符串排序)

    1. 题目 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个. 示例 1: 输入: [10,2] 输出: "102"示例 2: 输入: [ ...

  8. 剑指Offer:面试题33——把数组排成最小的数(java实现)(未完待续)

    问题描述: 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个.例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323. 思路1: ...

  9. 【剑指offer-Java版】08旋转数组的最小数字

    旋转数组最小数字:暴力方法就是遍历-有效的方法是二分,但是存在失效的情况 几个特别的测试用例需要注意下: 数组中含有多个相同的数字 最小数字就是第一个 public class _Q08 {publi ...

  10. 剑指offer——面试题51:数组中重复的数字

    剑指offer--面试题51:数组中重复的数字 Solution1: 20180910更新.利用数组做一次hash映射,时间复杂度为O(n)O(n)O(n),空间复杂度O(n)O(n)O(n). cl ...

最新文章

  1. SQL 解决从分组数据中总是挑选第一条数据的问题
  2. python 线程安全链表_教你用 Python 实现 HashMap 数据结构
  3. 关于JavaScript中name的意义冲突
  4. Spring IOC 容器源码分析 - 创建单例 bean 的过程
  5. AI:大力出奇迹?Bigger is better?AI下一代浪潮?—人工智能的大语言模型(LLMs)的简介、发展以及未来趋势
  6. Websocket实现Java后台主动推送消息到前台
  7. VTK:小部件之TexturedButtonWidget
  8. 在XenApp如何发布SAP的客户端(上)
  9. 手机修图软件测试,照片秒变高清修图软件APP
  10. android 工具 lve,Android Studio 4.0 新功能中的Live Layout Inspector详解
  11. 计算机软件登记委托开发合同,软件委托开发合同
  12. ArcEngine合并要素
  13. PDF阅读器开关“手型工具阅读文章”功能
  14. Vue-第三方库扩展
  15. web页超过2G以上大视频分片秒传方案
  16. C语言基础入门48篇_30_二维数组的定义与使用(二维数组的定义:type 数组名[行][列]、二维数组的初始化、二维数组的引用)
  17. 【DuiLib入门基础】九宫格corner属性详细解释
  18. S4D440Customcode adaption practice
  19. Kotlin高仿微信-第6篇-主页-我的
  20. Java微信开发_Exception_03_errcode:48001 errmsg:api unauthorized hint

热门文章

  1. Eratosthenes筛法求素数
  2. linux 永久添加路由表,Linux 添加永久静态路由的方法
  3. z tree 如何把选中的节点保存为标准的json格式_为什么MongoDB使用B-Tree?
  4. java显示字母数字组合_Java字母加数字组合比较大小
  5. 新版linux系统主机最低配置,Linux系统初始配置标准化
  6. Java应用案例分析_Java应用启动参数实例解析
  7. python中文字体奇怪_利用python检查 AS400的中文字问题
  8. centos7默认字体_如何更换CentOS(Linux)系统默认字体?
  9. tinyint数据类型php筛选时怎么判断_PHP从入门到精通(三)PHP语言基础
  10. easymock参数_EasyMock捕获参数