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)的方法,就是找到突然变小的那个元素,肯定是最小的。否则就说明所有元素一直变大,本来就是排序的,则返回第一个元素。

  1. public class Solution {
  2. public int findMin(int[] num) {
  3. if(num.length == 0){
  4. return 0;
  5. }
  6.  
  7. int min = num[0];
  8.  
  9. for(int i = 0; i < num.length; i++){
  10. if(num[i] < min){
  11. return num[i];
  12. }
  13. }
  14. return min;
  15. }
  16. }

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

  1. public class Solution {
  2. public int findMin(int[] num) {
  3. if(num.length == 0){
  4. return 0;
  5. }
  6.  
  7. if(num.length == 1){
  8. return num[0];
  9. }
  10.  
  11. int start = 0;
  12. int end = num.length - 1;
  13. int min = Integer.MAX_VALUE;
  14.  
  15. if(num[start] < num[end]){
  16. return num[start];
  17. }
  18.  
  19. while(start <= end){
  20. if(start == end){
  21. return Math.min(min, num[start]);
  22. }
  23. int mid = (start + end) / 2;
  24.  
  25. if(num[start] <= num[mid]){
  26. min = Math.min(min, num[start]);
  27. start = mid + 1;
  28. }else{
  29. min = Math.min(min, num[mid]);
  30. end = mid - 1;
  31. }
  32. }
  33. return min;
  34. }
  35. }

二分查找是一个很简单,却很难完全写对的算法,编程珠玑里写道,差不多只有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得不到更新,引起死循环。

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

  1. public class Solution {
  2. public int findMin(int[] num) {
  3. int start = 0;
  4. int end = num.length - 1;
  5. while(start <= end){
  6. int mid = (start + end) / 2;
  7. if(num[end] == num[mid]){
  8. return num[mid];
  9. }
  10. if(num[end] < num[mid]){
  11. start = mid + 1;
  12. }
  13. if(num[end] > num[mid]){
  14. end = mid;
  15. }
  16. }
  17. return -1;
  18. }
  19. }

二分查找的题目很多,基本原理就是这样,但是具体情况,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. python mongodb压力测试脚本

    $ pip install pymongo #!/usr/bin/env python #coding=utf-8 #Author: Ca0Gu0 from pymongo import MongoC ...

  2. (转)分布式文件存储FastDFS(二)FastDFS安装

    http://blog.csdn.net/xingjiarong/article/details/50559761 在前面的一篇中,我们分析了FastDFS的架构,知道了FastDFS是由客户端,跟踪 ...

  3. mvc 上传大文件

    <configuration> <system.web> <httpRuntime maxRequestLength="204800" useFull ...

  4. vc++6.0创建console32之.c的应用程序详解

    文件-->新建-->win32-->取一个名字,确定 文件-->新建-->c++Source-->取一个名字,记住以.c为后缀,确定 编写简单的程序调试

  5. js里的深度克隆

    ES6 数组克隆 let arr = [1,2,3,4,5]; let arr1 = [...a]; arr1 = ["a","b","c" ...

  6. Vim 写 C/C++ 的配置

    .vimrc 2018/08/08 更新 基本的配置,缩进显示行号等 给每个 C/C++ 文件添加头部,显示作者,文件创建时间 F5 编译执行 C/C++源代码 Ctrl + F 利用用 astyle ...

  7. 洛谷 2042 BZOJ 1500 NOI 2005 维护数列

    [题意概述] 维护一个数列,要求支持以下6种操作: [题解] 大Boss...可以用Treap解决 需要用到垃圾回收.线性建树. #include<cstdio> #include< ...

  8. GlobalSign 增强型(EV) SSL 证书

    GlobalSign 增强型(EV) SSL 证书,属于最高验证级别的EV SSL,验证域名所有权,进行严格的企业真实身份验证,证书标识企业组织机构名称,强化信任度,浏览器地址栏变绿色.提供40位/5 ...

  9. JavaWeb+MySql分页封装

    前段时间因为需要所以写一个JavaWeb+MySql的分页封装类,附上代码.技术有限写得不好请多多指教. 1.首先贴上Eneity类 package com.zx.pageUtil; import j ...

  10. mybatis源码阅读-执行器StatementHandle和ParameterHandler(五)

    StatementHandle 类图 各个实现类的作用 SimpleStatementHandler 用于使用Statement操作数据库(不会使用参数化查询?) PreparedStatementH ...