二分搜索的模板

引用自:http://www.cnblogs.com/yuzhangcmu/p/4049030.html

Find Minimum in Rotated Sorted Array

Question Solution
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.

SOLUTION 1:
这个题目trick的地方在于,它的旋转pivot次数未知。所以有可能它转了一圈又转回了原处

所以我们代码要处理2种情况:
我们还是用二分法来做。比起全部扫一次,二分法可以做到LogN的复杂度。

  1. Sorted

这种情况简单,先计算出mid的值,如果它处在左右的中间,证明这个数列是正常的sorted,直接返回左边。

  1. 中间断开(也就是说旋转过)
    我们的目的是要找出存在断口的地方。所以我们可以每次求一下mid的值,把mid 跟左边比一下,如果是正常序,就丢掉左边,反之丢掉右边,不断反复直到找到断口。
    分析一下:
    比如4 5 6 7 0 1 2 从中间断开后,它是由一个有序跟一个无序的序列组成的。
    如果left = 0, right = 6,mid = 3, 那么4, 5, 6, 7 是正序, 7, 0, 1, 2是逆序,所以我们要丢掉左边。这样反复操作,直到数列中只有2个数字,就是断开处,这题我们会得到7,0,返回后一个就可以了。

以下图示简单描述了通过三步操作逐步逼近断口处。每一次我们可以扔掉一半,速度是LogN.

注意,丢掉半边时,mid不可以丢掉,因为有可能mid就是答案。
例子: 3, 1, 2 的时候,3, 1是逆序,1, 2是正序,如果你扔掉1,2你就丢掉了答案。
View Code

SOLUTION 2:
采用九章算法的二分法模板来解:
这个模板最大的好处是 while(left < right - 1) 这样的话,终止时就一定是left = right - 1,而且mid 一直会是在中间,不会靠到left去。判断起来会相当
便利。
常见bug:
// bug 1: should not use l = m + 1 and r = m - 1.
// this may discard the minumul value.

A example: 3, 1, 2.

View Code

所以以后一定要多使用模板化的编程 ,特别是这里总结的二分法模板:
复制代码
1 while (l < r - 1) {
2 int m = l + (r - l) / 2;
3
4 // means that there is no rotate.
5 … 这里添加各种退出条件,比如找到了目标值等 8
9 // left side is sorted.
10 if (A[m] > A[l]) {
11 l = m;
12 } else {
13 r = m;
14 }
15 }

猜你喜欢

转载自blog.csdn.net/Zero_975/article/details/82765811
今日推荐