今天進行了阿里巴巴的面試,總體面試感覺還行,不出意外,我會進入到二面階段。
在面試過程中,面試官(槿涼)問了一個問題:我有一個算法問題,在一個有序數組中,如何查找已知的值的索引位置?
問題:有序數組中,如何查找已知的值的索引位置?
當聽到這個題目的時候,我的腦海中閃過Array.slice()?Array.find()?不會的,不會這麼簡單的,再看“有序數組”、“已知值”、“索引”等字眼,我就知道原來考察的是js的二分算法,也叫折半算法。
舉個例子:
// 定義有效數組
const Arr = [2,4,5,6,7,8,9];
// 方法調用
findIndex(Arr, 2) // 返回0
findIndex(Arr, 9) // 返回6
findIndex(Arr, 5) // 返回2
findIndex(Arr, 1) // 返回undefined
findIndex(Arr, 10) // 返回undefined
注意:二分查找(折半查找)只能在有序數組下進行,無序數組不能使用,如const Arr = [10,3,5,2,1,9],需要將無序數組進行升序排列後才能進行查找。
原理:用上面的例子,比如查找7的索引值,現將數組折半,let center = Math.floor(Arr.length -1 / 2),然後分別在[0, center]和[center, Arr.length - 1]範圍中查找,如果7在[center, Arr.length - 1]範圍中,繼續遞歸將[center, Arr.length - 1]範圍折半進行查找,週而復始,直到最後一個值,就是我們所需要的索引值。
實現findIndex方法
有了大白話的原理,接下來實現findIndex的方法就變得很容易了。
/*
* @params [Array] arr 有序的目標數組
* @params [Number] num 已知的值
* */
function findIndex(arr, num) {
// 數組長度
let length = arr.length;
// 初始化左邊範圍的索引
let left = 0;
// 初始化右邊範圍的索引
let right = length - 1;
// 折半中間值索引
let center = Math.floor((left + right) / 2);
// 循環查找
while(left <= length - 1 && right >= 0){
if (arr[center] === num) return center;
if (left === right) return "您查找的數不存在";
if (arr[center] > num) {
right = center-1;
center = Math.floor((left + right) / 2);
}else if (arr[center] < num) {
left = center + 1;
center= Math.floor((left + right) / 2);
}
}
}
現在想想,還不如一個循環遍歷來的方便,囧~
*************************************************************************************************************
喫完飯想想,二分查找也不是一無是處,在大規模的查找問題下,用折半遍歷的時間換取內存空間的解決,也還可以啊~,至少節省內存消耗嘛!
接下來我會專門開一個專題,去將這段時間的大廠面試題做一些講解。
*************************************************************************************************************
如果你看完這篇文章覺得有幫助,請點贊加收藏哦,只看不點贊等於耍流氓~
*************************************************************************************************************