剑指 Offer 11. 旋转数组的最小数字
❤️来自专栏《LeetCode基础算法题》 欢迎订阅❤️
@[TOC]
关于作者
- 作者介绍
🍓 博客主页:作者主页
🍓 简介:JAVA领域优质创作者🥇、一名在校大三学生🎓、在校期间参加各种省赛、国赛,斩获一系列荣誉🏆。
🍓 关注我:关注我学习资料、文档下载统统都有,每日定时更新文章,励志做一名JAVA资深程序猿👨💻。
1、题目
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
给你一个可能存在 重复 元素值的数组 numbers
,它原来是一个升序排列的数组,并按上述情形进行了一次旋转。请返回旋转数组的最小元素。例如,数组 [3,4,5,1,2]
为 [1,2,3,4,5]
的一次旋转,该数组的最小值为1。
实例1:
输入: [3,4,5,1,2]
输出: 1
实例2:
输入: [2,2,2,0,1]
输出: 0
注意:
2、思路🧠
方法一:暴力解法
- 根据题意,第一时间想到通过暴破来解决,用变量记录当前遍历过程中遇到的最小值,在遍历结束后,返回最小值即可。
- 为什么说暴力不优雅呢,因为我们知道数组被旋转,在遍历过程中,只要有数字小于
numbers[0]
,那么该数字一定是最小值。
方法二:二分优化
暴力不是我们的解题目标,暴力是进不了大厂的,所以小伙伴们在做题的时候还是要想一想优化的解法熬。
- 创建两个指针 L, R 分别指向
numbers
头和尾,计算出两指针之间的中间索引值 M,会出现以下三种情况: - 我们分别考虑
- M > R 时,最小值一定在 M 右侧,所以将 L 移动到 M + 1 的位置。
- M < R 时,最小值一定在 M 左侧也就是 M 的位置,所以将 R 移动到 M 的位置。
- M 既不大于 L 指针的值,也不小于 R 指针的值,意味着 M 可能等于 L 指针的值,或 R 指针的值,这时候唯一能继续进行程序的办法就是让 R 指针递减,来找最小值。
废话少说~上代码!
3、代码
第一次commit AC
class Solution {
public int minArray(int[] numbers) {
int i;
int index = 0;
for(i = 0;i < numbers.length - 1; i++){
if(numbers[i] >numbers[i + 1]) index = i + 1;
}
return numbers[index];
}
}
时间复杂度:O(n)
空间复杂度:O(1)
第二次commit AC
class Solution {
public int minArray(int[] numbers) {
int L = 0,R = numbers.length - 1;
while(L < R){
int M = L + ((R - L) >> 1);//这里是向下取整
if(numbers[M] > numbers[R]) {
L = M + 1;
}
else if(numbers[M] < numbers[R]) {
R = M;
}
else R -= 1;
}
return numbers[L];
}
}
时间复杂度:O(log n)
空间复杂度:O(1)
4、总结
该题目的使用二分查找的应用实例,首先要对二分法有所了解。
二分法模板:
public static int binarysearch(int arr[], int L, int R, int target){
int count = 0;
int M = (L + R) >> 1;
if(L > R) return -1;
if (target > arr[M]){
return binarysearch(arr, M + 1, R, target);
}else if(target < arr[M]){
return binarysearch(arr, L, M - 1, target);
}else {
return M;
}
}