剑指 Offer 11. 旋转数组的最小数字
双指针,二分法
题目链接-来源:力扣(LeetCode)
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。
示例 1:
输入:[3,4,5,1,2]
输出:1
思路:
最直观的思路就是,原数组为非递减数组,则旋转以后可以分解为两个非递减的子数组,我们依次两两比较数组中的数字,一旦出现 xi > xj (i < j) 的情况,输出 xj 即可。
进一步优化:
对有序数据的查找,容易想到二分法。为了直观说明,假设原数组为 [x0, x1, x2, x3, x4] 我们有 x1 <= x2 <= x3 <= x4,经过旋转后得 [x2, x3, x4, x0, x1],注意到一定有 最右侧元素 <= 最左侧元素,在本例中即 x1 <= x2,所找元素就应该顺着 x1 向左进行。
我们用头指针 left 指向数组最开始元素,用尾指针 right 指向数组末尾元素,则两指针的中间指针 mid = (left + right) / 2 有如下可能:
- nums[mid] (> nums[left]) > nums[right],即例子中的 x3,x4,那么所找元素就应该在mid的右边,于是令 left = mid + 1。
- nums[mid] < nums[right],即例子中的 x0,当然此时我们并不知道它就是最小元素,我们认为最小元素可能出现在其左边,于是令 right = mid。
- 对于相等情况,说明从mid到right很长距离上,甚至整个数组的元素有可能全部相等,我们慢慢缩小 right,否则可能会出现最小元素夹在若干个相等元素之间,被我们跨过的情况。
时间复杂度:O(log n)
空间复杂度:O(1)
实现:
1 | class Solution { |
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.