记录:玄学二分
我们接触二分都是从有序数列开始的。在有序数列中快速找数等等,二分非常适用。实际上,有序
的概念在这里太过狭窄了。
看这个题:
峰值元素是指其值大于左右相邻值的元素。
给你一个输入数组$nums$,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回
任何一个峰值
所在位置即可。你可以假设$nums[-1]=nums[n]=-\infty$。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-peak-element
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
你猜猜,这和二分有什么关系?
原来,题中描述的数列总满足以下性质:
- 如果$a[x]\le a[x+1]$,那么$x+1$及其右侧一定存在峰值(要么有峰值,要么是最后一个)。
- 如果$a[x]>a[x+1]$,那么$x$及其左侧一定存在峰值(要么有峰值,要么是第一个)。
所以,每次对中间的两个元素比较,看看哪边一定存在峰值就选取哪边的一半,一直进行,直到仅有一个元素,即为一个峰值。
仔细想想,二分本来就和有序
没什么关系。二分只是针对一个序列,通过检查中间的元素,判定哪一侧存在满足条件的元素,进一步缩小检查范围的算法。
有了这个想法,再看这道题:
已知一个长度为$n$的数组,预先按照升序排列,经由$1$到$n$次
旋转
后,得到输入数组。例如,原数组$nums = [0,1,2,4,5,6,7]$在变化后可能得到:
- 若旋转$4$次,则可以得到$[4,5,6,7,0,1,2]$
- 若旋转$7$次,则可以得到$[0,1,2,4,5,6,7]$
注意,数组$[a[0], a[1], a[2], ..., a[n-1]]$旋转一次 的结果为数组$[a[n-1], a[0], a[1], a[2], ..., a[n-2]]$。
给你一个元素值
互不相同
的数组$nums$,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的最小元素
。来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
说实话,做这道题之前,我先做了[search-in-rotated-sorted-array]
(https://leetcode-cn.com/problems/search-in-rotated-sorted-array/),所以有了想法。
这个数组有个特点,就是不管怎么旋转,从中间断开,至少一半是有序的。
所以我们只要找有序一侧第一个元素和无序一侧最小元素的最小值就好了。
无序一侧最小元素怎么找呢?我们整体就是在干这个事嘛(无序数组找最小),递归调用,完毕。