JS千面之數組的二分查找

今天進行了阿里巴巴的面試,總體面試感覺還行,不出意外,我會進入到二面階段。

在面試過程中,面試官(槿涼)問了一個問題:我有一個算法問題,在一個有序數組中,如何查找已知的值的索引位置?

問題:有序數組中,如何查找已知的值的索引位置?

當聽到這個題目的時候,我的腦海中閃過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);
    }
  }
}

現在想想,還不如一個循環遍歷來的方便,囧~ 
*************************************************************************************************************
喫完飯想想,二分查找也不是一無是處,在大規模的查找問題下,用折半遍歷的時間換取內存空間的解決,也還可以啊~,至少節省內存消耗嘛!
接下來我會專門開一個專題,去將這段時間的大廠面試題做一些講解。

*************************************************************************************************************

如果你看完這篇文章覺得有幫助,請點贊加收藏哦,只看不點贊等於耍流氓~

*************************************************************************************************************

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章