题目地址:
今天刷库存管理I(旋转数组的最小数字),大家有兴趣可以点上看看题目要求,试着做一下。
难度:简单
我们看看题解:
方法1,直接遍历(时间复杂度(n))
方法2,二分查找(时间复杂度(logn))
审题目+事例+提示:
光看这题目其实不太好懂的,建议先看一下剑指offer原题。
这里核心概念是旋转数组,它是原数组经多次旋转得到的:
例如:nums=[3,4,5,1,2] 是原数组nums=[1,2,3,4,5,]
经3次旋转得到的。
·由此就可以发现,旋转数组实际可分为两个子数组,
即左排序数组和右排序数组
·而右排序数组首元素stock[x]是两个数组的分界元素,
即我们要寻找的最小数字(其中x被称为旋转点)
·由下图我们也可以得到一个性质,
左排序数组的任一元素>=右排序数组的任一元素
思路(二分法):
- 创建两个指针,low和high分别指向数组两端
- 循环二分:设二分的中点m=low+(high-low)/2,
(‘/’表示向下取整除法,即恒有low<=m<high)
·当stock[m]>stock[high]时,则m在左排序数组,即旋转点x在区间[m+1,high],
故low=m+1
·当stock[m]<stock[high]时,则m在右排序数组,即旋转点x在区间[low,m],故high=m
·当stock[m]==stock[high]时,无法判断m在哪个数组
则方法一:high--,缩小判断范围
方法二:线性查找,即遍历比较剩下区间的元素
3、最后当low==high时跳出循环,返回stock[low]
代码:
class Solution {
public int stockManagement(int[] stock) {
int low = 0, high = stock.length - 1;
while (low < high) {
int m = (low + high) / 2;
if (stock[m] > stock[high]) low = m + 1;
else if (stock[m] < stock[high]) high = m;
else high--;
}
return stock[low];
}
}
代码:
class Solution {
public int stockManagement(int[] stock) {
int low = 0, high = stock.length - 1;
while (low < high) {
int m = (low + high) / 2;
if (stock[m] > stock[high]) low = m + 1;
else if (stock[m] < stock[high]) high = m;
else {
int x = low;
for(int k = low + 1; k < high; k++) {
if(stock[k] < stock[x]) x = k;
}
return stock[x];
}
}
return stock[low];
}
}