题目如下
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
解题思路:
有三种思路
- 很简单了,遍历数组取得最小值。
我最开始就是这种想法。。。太low了function minNumberInRotateArray(rotateArray) { if( rotateArray.length === 0 ){ return 0; }else{ let len = rotateArray.length; let min = rotateArray[0]; for(var i = 1 ; i < len ; i++){ if( rotateArray[i] < min ){ min = rotateArray[i]; } } return min; } }
- 对上面的方法进行部分优化,可以将数组看出两个非递减的数组,a[x1…xn] b[y1…yn]
显然最小值就是y1,在a中x1到xn是非递减的,所以遍历时,找到第一个a[n] > a[n+1]的n即可,结果就是a[n+1]
同时对于[1,1,1,1]这种恒等的数组需要做特殊处理function minNumberInRotateArray2(rotateArray) { if( rotateArray.length === 0 ){ return 0; }else{ let len = rotateArray.length; for(var i = 1 ; i < ( len - 1 ) ; i++){ if( rotateArray[i] > rotateArray[ i + 1] ){ return rotateArray[i+1] } if( i === len - 1){ return rotateArray[i]; } } } }
- 这个是比较高级的一种方法了,就是利用二分法进行查找
同上面的方法,将数组arr看作两个非递减的数组a[x1…xn] , b[y1…yn]
3-1. 取left = 0, right =arr.length -1;
3-2. 取left和right的中间值 mid
3-3. 拿mid的对应的值与left对应的值进行比较
如果arr[mid] >= arr[left],说明mid位于a[x1…xn]中,最小值b[y1]位于mid和right中,设置left=mid
如果arr[mid] < arr[left],说明mid位于b[y1…yn]中,最小值b[y1]位于left和mid中,设置right=mid
3-4. 重复上述步骤3-2和3-3直到 right - left == 1
3-5. 结果arr[left] = a[xn], arr[right] = b[y1],最小值为arr[right]function minNumberInRotateArray(rotateArray) { if( rotateArray.length === 0 ){ return 0; }if( rotateArray.length === 1){ return rotateArray[0]; }else{ let len = rotateArray.length; let left = 0; let right = len - 1; while( right - left !== 1 ){ let center = Math.floor( (left + right) / 2 ); if( rotateArray[center] >= rotateArray[left]){ left = center; }else{ right = center; } } return rotateArray[right]; } }