https://oj.leetcode.com/problems/find-minimum-in-rotated-sorted-array/

Suppose a sorted array is rotated at some pivot unknown to you beforehand.

(i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2).

Find the minimum element.

You may assume no duplicate exists in the array.

解题思路:

最朴素的O(n)的方法,就是找到突然变小的那个元素,肯定是最小的。否则就说明所有元素一直变大,本来就是排序的,则返回第一个元素。

public class Solution {
public int findMin(int[] num) {
if(num.length == 0){
return 0;
} int min = num[0]; for(int i = 0; i < num.length; i++){
if(num[i] < min){
return num[i];
}
}
return min;
}
}

不过本题还有一个二分查找的方法,可以将时间复杂度降为O(lgN)。代码如下。

public class Solution {
public int findMin(int[] num) {
if(num.length == 0){
return 0;
} if(num.length == 1){
return num[0];
} int start = 0;
int end = num.length - 1;
int min = Integer.MAX_VALUE; if(num[start] < num[end]){
return num[start];
} while(start <= end){
if(start == end){
return Math.min(min, num[start]);
}
int mid = (start + end) / 2; if(num[start] <= num[mid]){
min = Math.min(min, num[start]);
start = mid + 1;
}else{
min = Math.min(min, num[mid]);
end = mid - 1;
}
}
return min;
}
}

二分查找是一个很简单,却很难完全写对的算法,编程珠玑里写道,差不多只有10%的程序员能正确的实现它。问题主要处在边界变量的定义,和循环条件的定义上。让我们从程序的开头看起。

将end定义为length - 1,就意味着这是一个[0, length - 1]的左右都闭合的区间,所以循环的条件一定是start <= end。所以再到循环内部,start = mid + 1, end = mid - 1,都是因为这是一个闭合的区间,这样做才不会漏元素。

如果end定义为length,那么就意味着这个区间是左闭合有开的,[0, length)。所以后面while的条件就变为start < end,循环内部,start = mid + 1, end = mid。

这样理解起来就不会出错。其实这就是循环不变式的概念,loop invariant。可以参考下面的页面,对于这个比较基础的知识介绍的很好。

http://www.cppblog.com/converse/archive/2009/09/21/96893.aspx

update: 2015/03/11

下面一段我写的,更为简洁的代码。看几个例子,7 8 0 1 2 3 4 5 6,mid=2;3 4 5 6 7 8 0 1 2,mid=7。

mid > end的时候,代表前面是排序的,可能折断点在后面,于是start=mid+1。

mid < end的时候,代表后面是排序的,可能折断点在前面,但是这时候不能end = mid - 1。为什么?看一个例子,4 5 0 1 2。这时mid < end,但是mid就是折断点,所以这时end = mid。

mid == end的时候,说明当前mid就是最小值。

为什么mid要和end比较,不能和start?因为除非在start==end的情况,否则mid不可能等于end,但是start可能等于mid,比如只有两个元素,[2,1],这时start==mid<end,所以返回的是错误的2。

另外还要注意一点。while内部更新start和end的各个条件要符合互相没有交集,但是合起来又可以组成全集的原理。因为前半句违背了,可能一次更新多次start和end,这样有些范围就跳过不搜索了。后半句违背了,可能使得start和end得不到更新,引起死循环。

这个性质其实也和上面说的循环不变式同理,需要体会。

public class Solution {
public int findMin(int[] num) {
int start = 0;
int end = num.length - 1;
while(start <= end){
int mid = (start + end) / 2;
if(num[end] == num[mid]){
return num[mid];
}
if(num[end] < num[mid]){
start = mid + 1;
}
if(num[end] > num[mid]){
end = mid;
}
}
return -1;
}
}

二分查找的题目很多,基本原理就是这样,但是具体情况,mid的值和哪个值比较,状态变化和终止的条件,变化万千,需要细细体会。

这道题是二分查找里比较经典的题目,也比较灵活,相应条件的定义和start、end的转换可以有多种写法。

Find Minimum in Rotated Sorted Array 典型二分查找的更多相关文章

  1. Search in Rotated Sorted Array(二分查找)

    Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 migh ...

  2. Find Minimum in Rotated Sorted Array I&&II——二分查找的变形

    Find Minimum in Rotated Sorted Array I Suppose a sorted array is rotated at some pivot unknown to yo ...

  3. [LeetCode] Find Minimum in Rotated Sorted Array II 寻找旋转有序数组的最小值之二

    Follow up for "Find Minimum in Rotated Sorted Array":What if duplicates are allowed? Would ...

  4. [LeetCode] Find Minimum in Rotated Sorted Array 寻找旋转有序数组的最小值

    Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 migh ...

  5. 【leetcode】Find Minimum in Rotated Sorted Array I&&II

    题目概述: Suppose a sorted array is rotated at some pivot unknown to you beforehand.(i.e., 0 1 2 4 5 6 7 ...

  6. Leetcode | Find Minimum in Rotated Sorted Array I && II

    Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 migh ...

  7. 简单的算法题, Find Minimum in Rotated Sorted Array 的Python实现。

    简单的算法题, Find Minimum in Rotated Sorted Array 的Python实现. 题目: Suppose a sorted array is rotated at som ...

  8. [OJ] Find Minimum in Rotated Sorted Array II

    LintCode 160. Find Minimum in Rotated Sorted Array II (Medium) LeetCode 154. Find Minimum in Rotated ...

  9. LeetCode OJ 154. Find Minimum in Rotated Sorted Array II

    Follow up for "Find Minimum in Rotated Sorted Array":What if duplicates are allowed? Would ...

随机推荐

  1. 为什么有些异常throw出去需要在函数头用throws声明,一些就不用

    throw new IllegalStateException(".");不用在函数头声明throws IllegalStateExceptionthrow new IOExcep ...

  2. jenkins配置发送测试结果邮件

    简单版: https://www.cnblogs.com/gcgc/p/5631385.html https://blog.51cto.com/qicheng0211/1919341 升级版 http ...

  3. FTP服务器访问主动模式、被动模式

    在公司里面,经常需要访问外网FTP取资料等情况.但是有时用windows界面访问经常遇到各种问题. 下面介绍两种客户端是如何访问ftp服务器. 首先我们需要说明:防火墙,是阻拦外界与内部的通讯的一道关 ...

  4. DNS详细解析过程【转】

    转自:http://blog.csdn.net/crazw/article/details/8986504 先说一下DNS的几个基本概念: 一. 根域 就是所谓的“.”,其实我们的网址www.baid ...

  5. Spring框架学习之SpringAOP(二)

    AOP概念 AOP(Aspect-Oriented Programming,面向切面编程),AOP是OOP(面向对象编程)的补充和完善 AOP的核心思想就是“将应用程序中的商业逻辑同对其提供支持的通用 ...

  6. ASP.NET大闲话:ashx文件有啥用

    在VS中右击项目,添加新项,我们找到.ashx文件在新建项模板中叫做“一般处理程序”,那么这个一般处理程序用来干吗的呢? 我们可以这样地简单理解,嗯,不需搞得太复杂,它就类似.aspx文件,用于处理传 ...

  7. 使用Autofac 依赖注入及 swagger 之startup配置

    言语有限,代码如下: public IServiceProvider ConfigureServices(IServiceCollection services) { services .AddCor ...

  8. 2019字节跳动冬令营day7娱乐赛19题题解

    啊没去听讲题,也没发纸质题解,电子版题解也没有 为最后几个unsolve自闭了一段时间才全都A掉 3个队友写的我没看的题通过人数蛮多就不管了 题目地址:https://pan.baidu.com/s/ ...

  9. Spring MVC学习总结(9)——Spring MVC整合swagger自动生成api接口文档

    Swagger 号称:世界最流行的API框架,官网:http://swagger.io/,Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务.总 ...

  10. [网络流24题#9] [cogs734] 方格取数 [网络流,最大流最小割]

    将网格分为两部分,方法是黑白染色,即判断(i+j)&1即可,分开后从白色格子向黑色格子连边,每个点需要四条(边界点可能更少),也就是每个格子周围的四个方向.之后将源点和汇点分别于黑白格子连边, ...