旋转数组的最小数字&搜索旋转排序数组
旋转数组的最小数字&搜索旋转排序数组
旋转数组最小数字
题目
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个升序的数组的一个旋转,输出旋转数组的最小元素。
例如数组 {3,4,5,1,2}{3,4,5,1,2} 为 {1,2,3,4,5}{1,2,3,4,5} 的一个旋转,该数组的最小值为 11。
数组可能包含重复项。
注意:数组内所含元素非负,若数组大小为 00,请返回 −1−1。
样例
1 | 输入:nums = [2, 2, 2, 0, 1] |
解法:二分查找
题目中有排序两字,自然较优的解是涉及到二分法的
假设我们用下图表示数组,水平线代表数字相同,横坐标代表数字下标
我们发现除了最后水平的一段(黑色水平那段)之外,其余部分满足二分性质:
竖直虚线左边的数满足 $numbers[i] ≥ numbers[0]$ ;
而竖直虚线右边的数不满足这个条件。
我们要找的便是不满足上诉性质的那段中的最小值。
所以我们先将最后水平的一段删除 , 使得右半段不满足 $numbers[i] ≥ numbers[0]$ ,而是严格满足 $numbers[i] < numbers[0]$。
另外,如果处理数组完全单调的情况:
当删除最后一段后,如果剩下的最后一个大于等一第一个数,说明数组完全单调。
1 | class Solution { |
搜索旋转数组
数组旋转后可画出如下图:
橙色线表示的就是旋转后数组的左右两个部分。不难发现,如果下标落在右半部分,则一定有 $nums[mid] <= nums[nums.length-1]$
判断 $nums[mid] <= nums[nums.length-1]$ 是否成立
- 成立:说明当前mid落在了数组的右半部分,而我们要找的最小值其实就是右半部分的开头,故更新区间为 $[l,mid]$ 。
- 否则:说明mid落在了旋转数组的左半部分,那么右半部分的起点则在 $[mid+1, r]$
总之,要找满足 $nums[mid] <= nums[nums.length-1]$ 的最小值
第二阶段
找到最小值后,假如最小值的下标是 min ,数组便可以分为有序的两半 $[l, min-1]$ 和 $[min, r]$ 此时判断 $target<=nums[nums.length-1]$ 。
若成立,可以再右半部分中找target,因为target如果在右半部分的话,一定大于 $nums[nums.length-1]$, 那么久应该去左半边 $[l, min-1]$ 中找 target
1 | class Solution { |