剑指offer11 旋转数组的最小数字
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个升序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
数组可能包含重复项。
注意:数组内所含元素非负,若数组大小为0,请返回-1。
样例
输入:nums=[2,2,2,0,1]
输出:0
思路:
首先判断数组left位置上的数值是否小于right位置上的,若是,说明数组是一个递增的数组,则直接返回nums[left]上的数值。否则,开始进入循环:
判断数组中是否只有两个数值,若是,则直接结束并返回right位置上的数值。
判断right、left、mid三个位置上的元素是否都重复,若都重复则搞不清最小值是在前半段还是后半段,只能顺序遍历数组,并直接返回最小值。如:[1,0,1,1,1]和[1,1,1,0,1]
right、left、mid上的三个值不相等时,若mid上的数值大于或者等于left,则最小值在后半段, 否则在前半段。
AcWing-22 C++ code:
class Solution {
public:
int findMin_n(vector<int>& nums, int left, int right){
int min = nums[left];
for(int i = left; i <= right; i++){
if(min > nums[i]){
min = nums[i];
}
}
return min;
}
int findMin(vector<int>& nums) {
if(nums.size() == 0){
return -1;
}
int n = nums.size();
for(int i = 0; i < n; i++){
if(nums[i] < 0){
return -1;
}
}
int left = 0;
int right = n - 1;
int mid = left;
while(nums[right] <= nums[left]){
if(right - left == 1){
mid = right;
break;
}
mid = left + (right - left) / 2;
if(nums[left] == nums[right] && nums[mid] == nums[left]){
return findMin_n(nums, left, right);
}
if(nums[mid] >= nums[left]){
left = mid;
}else{
right = mid;
}
}
return nums[mid];
}
};
牛客网 C++ code:
class Solution {
public:
int minNumberInRotateArrayCore_n(vector<int> &nums){
int res = nums[0];
for(auto x : nums){
if(x < res){
res = x;
}
}
return res;
}
int minNumberInRotateArrayCore_logn(vector<int> &nums){
int left = 0;
int right = nums.size() - 1;
int mid = left + (right - left) / 2;
while(nums[left] >= nums[right]){
if(right - left <= 1){
break;
}
mid = left + (right - left) / 2;
if(nums[left] <= nums[mid]){
left = mid;
}else{
right = mid;
}
}
return nums[left] > nums[right] ? nums[right] : nums[left];
}
int minNumberInRotateArray(vector<int> nums) {
if(nums.size() == 0){
return 0;
}else if(nums.size() == 1){
return nums[0];
}
int left = 0;
int right = nums.size() - 1;
int mid = left + (right - left) / 2;
if(nums[left] == nums[mid] && nums[left] == nums[right]){
return minNumberInRotateArrayCore_n(nums);
}else{
return minNumberInRotateArrayCore_logn(nums);
}
}
};
AcWing-22 python code:
class Solution:
def findMin_n(self, nums, left, right):
min_num = nums[left]
for i in range(left, right + 1):
if min_num > nums[i]:
min_num = nums[i]
return min_num
def findMin(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if len(nums) == 0:
return -1
n = len(nums)
for i in range(n):
if nums[i] < 0:
return -1
left = 0
right = n - 1
mid = left
while nums[right] <= nums[left]:
if right - left == 1:
mid = right
break
mid = left + (right - left) // 2
if nums[left] == nums[right] and nums[left] == nums[mid]:
return self.findMin_n(nums, left, right)
if nums[mid] >= nums[left]:
left = mid
else:
right = mid
return nums[mid]