持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天,点击查看活动详情
题目
把一个数组最开始的若干个元素搬到数组的末尾。输入一个递增排序数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}一个旋转,该数组最小值为1。
解题思路
全局遍历法
最简单解题方法是从头到尾遍历数组找到最小元素,该方法最为简单粗暴。
int max = numbers[0];
for(int i = 1; i < numbers.length; i++) {
if(numbers[i] > max){
max = numbers[i];
}
}
return max;
子数组分割法
虽然遍历全部的方法简单粗暴但没有利用到题目所说旋转数组题意。旋转数组实际上可以划分为两个排序子数组,而前面子数组元素都大于或等于后面子数组元素。因此可以根据该规则特点发现最小元素就是两个子数组的分界线,只需要在数组中找到比前一个元素小的元素即可。
for(int i = 1; i < numbers.length; i++) {
if(numbers[i] < numbers[i - 1]) { // 可以使用已知条件获取最小值
return numbers[i];
}
}
return numbers[0];
二分法
同样根据最小元素是两个子数组分界线,在排序数组中使用二分法思路来找到最小元素。利用双指针分别指向数组第一个元素和最后一个元素。
- 可知第一个元素是大于或者等于最后一个元素的。
- 采用二分法找到双指针中间元素是否大于右边的值。
- 大于右边值则缩小左边范围,左指针指向中间值下标。
- 小于右边值则缩小右边范围,右指针指向中间值下标。
- 直到双指针越界。
int left = 0;
int right = nums.length - 1;
while (left < right) { // 指针左小于指针 则继续找最小值
int mid = left + (right - left) / 2; // 双指针中间值
if (nums[mid] > nums[right]) { // 中间值是否大于最右的值
left = mid + 1; //大于则缩小左边范围
} else {
right = mid; // 小于则缩小右边范围
}
}
return nums[left];