154. 寻找旋转排序数组中的最小值 II/面试题11. 旋转数组的最小数字(一般) 假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
请找出其中最小的元素。
注意数组中可能存在重复的元素。
示例 1: 输入: [1,3,5]
输出: 1
示例 2: 输入: [2,2,2,0,1]
输出: 0
说明: 这道题是 寻找旋转排序数组中的最小值 的延伸题目。 允许重复会影响算法的时间复杂度吗?会如何影响,为什么?
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/find-minimum-in-rotated-sorted-array-ii
思路: 思路是二分查找的扩展思想,如果中间比右边大,则旋转点一定正在数组后面,否则一定在数组前面,当出现类似(1,1,1,1,0,0,1,1)这类情况无法进行左右甄别,随机选择一边进行抉择,比如选前半部分,如果mid的值和最左的值相等,则每次将high向前移动一位,不等的话可以选择直接将high = mid
参考题解
https://leetcode-cn.com/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof/solution/mian-shi-ti-11-xuan-zhuan-shu-zu-de-zui-xiao-shu-3/
回看记录200625 numbers[m] == numbers[j]
j=j−1 只需证明每次执行此操作后,旋转点 x 仍在 [i, j]区间内即可
这样就可以不用单独判断,或者是随意选一个方向进行压缩,直接high–即可,比剑指offer上少了一个判断,但是相当于有些情况下复杂度高了点,没有特殊分析
代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class Solution { public int findMin (int [] nums) { if (nums == null || nums.length == 0 ) return -1 ; int low = 0 ,high = nums.length-1 ; while (low<high){ if (nums[low]<nums[high]) return nums[low]; int mid = low + ((high-low)>>1 ); if (nums[mid]>nums[high]){ low = mid+1 ; }else if (nums[mid]<nums[low]){ high = mid; }else { if (nums[mid]==nums[low]){ high--; }else { high = mid; } } } return nums[low]; } }
代码2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 //回看记录 class Solution { public int minArray(int[] numbers) { int i = 0, j = numbers.length - 1; while (i < j) { int m = (i + j) / 2; if (numbers[m] > numbers[j]) i = m + 1; else if (numbers[m] < numbers[j]) j = m; else j--; } return numbers[i]; } } 作者:jyd 链接:https://leetcode-cn.com/problems/xuan-zhuan-shu-zu-de-zui-xiao-shu-zi-lcof/solution/mian-shi-ti-11-xuan-zhuan-shu-zu-de-zui-xiao-shu-3/