把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素。例如,数组 [3,4,5,1,2] 为 [1,2,3,4,5] 的一个旋转,该数组的最小值为1。
方法1 暴力
关键点:
1.正常排序的情况下,最小就是第一个;
2.旋转过的,则找出第一个数字小于前一个数字。
从下标为0的元素开始遍历;
每次进行比较,如果当前元素比相邻的下一元素大,则对应的下一个元素即为最小值;
如果遍历到最后一个元素都没有出现过上述情况,则下标为0的元素为最小元素。
var minArray = function(numbers) {
if(numbers.length==1)
return numbers[0];
for(var i=1;i<numbers.length;i++){
if(numbers[i]<numbers[i-1])
return numbers[i];
}
return numbers[0];
};
方法2 排序
先排序,再输出第一个元素,就是最小的元素
var minArray = function(numbers) {
var arr=numbers.sort(function(a,b){return a-b});
return arr[0];
};
方法3 二分查找
题目中给出的是半有序数组,虽然传统二分告诉我们二分只能用在有序数组中,但事实上,仍然可以使用二分思想。
思路:数组中最特殊的位置是左边位置 left 和右边位置 right,将它们与中间位置 mid 的值进行比较,进而判断最小数字出现在哪里。
用左边位置 left 和中间位置 mid 的值进行比较是否可以?
举例:[3, 4, 5, 1, 2] 与 [1, 2, 3, 4, 5] ,此时,中间位置的值都比左边大,但最小值一个在后面,一个在前面,因此这种做法不能有效地减治。
用右边位置 right 和中间位置 mid 的值进行比较是否可以?
举例:[1, 2, 3, 4, 5]、[3, 4, 5, 1, 2]、[2, 3, 4, 5 ,1],用右边位置和中间位置的元素比较,可以进一步缩小搜索的范围。
补充说明:遇到 nums[mid] == nums[right] 的时候,不能草率地下定结论最小数字在哪一边,但是可以确定的是,把 right 舍弃掉,并不影响结果。
var minArray = function(numbers) {
var left=0;
var right=numbers.length-1;
if(right==0)
return numbers[0];
while(left<right){
var mid=left+Math.floor((right-left)/2);
if(numbers[mid]>numbers[right]){
left=mid+1;
}else if(numbers[mid]<numbers[right]){
right=mid;
}else{
right--;
}
}
return numbers[left];
};