旋转数组的最小数字
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0
思路
把数组从大到小排列,然后输出最小数字,这种思路的时间复杂度是O(n)也没有利用旋转数组的一些特点,并不是题的意图,算是一种方法。
旋转之后的数组实际上可以划分为两个排序的子数组,而且前面的子数组的元素都大于或者等于后面的子数组的元素。最小的元素刚好是这两个子数组的分界线。在排序的数组中可以用二分查找实现O(logn)的查找。
1.我们用两个指针low和high分别指向数组的第一个元素和最后一个元素。按照题目的旋转的规则,第一个元素应该是大于等于最后一个元素的;但是如果不是旋转,第一个元素肯定小于或等于最后一个元素。
2.找到数组的中间元素。中间元素大于最后一个元素,则中间元素位于前面的递增子数组,此时最小元素位于中间元素的后面。我们可以让第一个指针low指向中间元素。
3.中间元素小于最后一个元素,则中间元素位于后面的递增子数组,此时最小元素位于中间元素的前面。我们可以让第二个指针high指向中间元素。
4.中间元素等于最后一个元素,则将第二个指针向前移,然后继续比较。
代码
function minNumberInRotateArray(rotateArray)
{
// write code here
rotateArray.sort(function(a,b){
if(a<b)return -1;
else return 1
});
return rotateArray[0];
}
//方法二:调用Math.min方法
//Math.min 参数里面不支持数组Math.min([param1,param2]);但它支持Math.min(param1,param2,…)
if(rotateArray.length==0){
return 0;
}
return Math.min.apply(null,rotateArray);
//apply第一个参数给了一个null,是因为没有对象去调用这个方法,只需要用这个方法计算得到结果,所以直接传递了一个null过去
//example
/*
function a(xx) {
this.b = xx;
}
var o = {};
a.apply(o, [5]); //a.apply(null, [5]);下面o.b结果就是undefined
alert(a.b); // undefined
alert(o.b); // 5
*/
//第三种
function minNumberInRotateArray(rotateArray)
{
var len = rotateArray.length
if (len == 0){
return 0
}else{
var low = 0;
var high = len-1;
while(low<high){
var mid = low + Math.floor((high - low) / 2);
if(rotateArray[mid] > rotateArray[high]){
low = mid + 1;
}else if(rotateArray[mid] == rotateArray[high]){
high = high - 1;
}else{
high = mid;
}
}
return rotateArray[low];
}
}
知识点
sort() 方法用于对数组的元素进行排序。
如果调用该方法时没有使用参数,将按字母顺序对数组中的元素进行排序,说得更精确点,是按照字符编码的顺序进行排序。要实现这一点,首先应把数组的元素都转换成字符串(如有必要),以便进行比较。
如果想按照其他标准进行排序,就需要提供比较函数,该函数要比较两个值,然后返回一个用于说明这两个值的相对顺序的数字。比较函数应该具有两个参数 a 和 b,其返回值如下:
若 a 小于 b,在排序后的数组中 a 应该出现在 b 之前,则返回一个小于 0 的值。
若 a 等于 b,则返回 0。
若 a 大于 b,则返回一个大于 0 的值。
min() 方法可返回指定的数字中带有最低值的数字。
Function.apply()是JS的一个OOP特性,一般用来模拟继承和扩展this的用途,对于上面这段代码,可以这样去理解:
XXX.apply是一个调用函数的方法,其参数为:apply(Function, Args),
Function为要调用的方法,Args是参数列表,当Function为null时,默认为上文,
即
Math.max.apply(null, arr)
可认为是
apply(Math.max, arr)
然后,arr是一个参数列表,对于max方法,其参数是若干个数,即
Math.max(a, b, c, d, …)
当使用apply时,把所有参数加入到一个数组中,即
arr = [a, b, c, d, …]
代入到原式,
Math.max.apply(null, [a, b, c, d, …])
实际上等同于
Math.max(a, b, c, d, …)
在此处,使用apply的优点是在部分JS引擎中提升性能。