题目描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
示例1
返回值
复制1
思路:
1.二分:
根据题意我们可以知道,给出的数组可以被视为由一个(未旋转)或两个(发生选择)非递减数组组成。
定义ps为数组开始下标,pe为数组结束下标,mid=(ps+pe)/2
那么:如果array[mid] >= array[pe],则最小值一定在mid右侧
如果array[mid] <= array[ps],则最小值一定为mid或在mid左侧
这样我们就可以在迭代求解时,每次都将问题规模缩小一半,进而缩短时间。
我们可以递归的实现:
class Solution { public: int minNumberInRotateArray(vector<int> rotateArray) { int len = rotateArray.size(); if(len == 0) return 0; int minn = Solve(rotateArray,0,len-1); return minn; } int Solve(vector<int> rotateArray, int ps, int pe) { if(ps >= pe) return rotateArray[ps]; int mid = (ps+pe)/2; int right_n = rotateArray[ps], left_n = rotateArray[ps]; if(rotateArray[mid] >= rotateArray[pe]) { right_n = Solve(rotateArray,mid+1,pe); } else if(rotateArray[mid] <= rotateArray[ps]) { left_n = Solve(rotateArray,ps,mid); } return min(right_n,left_n); } };
也可以非递归的实现:
class Solution { public: int minNumberInRotateArray(vector<int> rotateArray) { int len = rotateArray.size(); if(len == 0) return 0; int minn = Solve(rotateArray,0,len-1); return minn; } int Solve(vector<int> rotateArray, int ps, int pe) { int ans = rotateArray[ps]; while(ps < pe) { int mid = (ps+pe)/2; if(rotateArray[mid] >= rotateArray[pe]) { ps = mid+1; } else { pe = mid; } } ans = min(ans,rotateArray[ps]); return ans; } };
2.暴力:
暴力最容易想到的思路,但是如果裸暴力你可能剑指不到offer
假设最小值为minn,对于array[k]==minn,肯定存在k使得array[k] < array[k-1](特殊情况除外:数组未发生旋转或数组内所有元素大小相同)
我们同时从数组的两端寻找这样的k值即可,实现时有些小技巧来帮助我们节省时间
static const auto _=[](){ ios::sync_with_stdio(false); cin.tie(nullptr); return nullptr; }(); class Solution { public: int minNumberInRotateArray(vector<int> rotateArray) { for(int i=0,j=rotateArray.size()-1;i<j;i++,j--){ if(rotateArray[i]>rotateArray[i+1]) return rotateArray[i+1]; if(rotateArray[j]<rotateArray[j-1]) return rotateArray[j]; } return rotateArray.empty()?0:rotateArray[0]; } };