一天一個仿lodash函數實現-sortedIndex

拖了一週了,上週一直在忙(其實是sortedIndex沒咋理解好)

sortedIndex 從有序數組中找到指定數該插入的位置,用的是二分法的方式解決。

有兩個關鍵點:有序數組,二分法

所以實現上是這樣的:

function sortedIndex(arr, value){
  let head = 0;
  let tail = arr.length - 1;
  let mid;
  while(head<tail){
    mid = Math.floor((head+tail)/2);
    if(arr[mid]<value){
      head = mid + 1;
    } else {
      tail = mid;
    }
  }
  return tail;
}

在二分法中,我有個模糊的疑問,就是爲什麼head要mid+1,而tail不用mid-1?

配套的幾個不必多說,其實就是多了判斷條件或者返回罷了,實際上這幾個函數在lodash源碼裏是抽離出底層邏輯函數,來分開調用的。

function sortedIndexBy(arr, val, it){
  const iteratee = typeof it === 'string'?a=>a[it]:it
  let head = 0;
  let tail = arr.length - 1;
  let mid;
  while(head<tail){
    mid = Math.floor((head+tail)/2);
    if(iteratee(arr[mid])<iteratee(val)){
      head = mid + 1;
    } else {
      tail = mid;
    }
  }
  return tail;
}

function sortedIndexOf(arr, val){
  let head = 0;
  let tail = arr.length - 1;
  let mid;
  while(head<tail){
    mid = Math.floor((head+tail)/2);
    if(arr[mid]<val){
      head = mid + 1;
    } else {
      tail = mid;
    }
  }
  return arr[tail]===val?tail:-1;
}

關於sortedLastIndex則是查找出最後的一個index,假設數組中間有許多相等的匹配元素,函數則需要返回最後的一個的位置,這個其實很簡單,在原有的判斷中加多一個=判斷即可。

function sortedLastIndex(arr, val){
  let head = 0;
  let tail = arr.length - 1;
  let mid;
  while(head<tail){
    mid = Math.floor((head+tail)/2);
    if(arr[mid]<=val){
      head = mid + 1;
    } else {
      tail = mid;
    }
  }
  return tail
}

function sortedLastIndexBy(arr, val, it){
  const iteratee = typeof it === 'string'?a=>a[it]:it
  let head = 0;
  let tail = arr.length - 1;
  let mid;
  while(head<tail){
    mid = Math.floor((head+tail)/2);
    if(iteratee(arr[mid])<=iteratee(val)){
      head = mid + 1;
    } else {
      tail = mid;
    }
  }
  return tail;
}

function sortedLastIndexOf(arr, val){
  let head = 0;
  let tail = arr.length - 1;
  let mid;
  while(head<tail){
    mid = Math.floor((head+tail)/2);
    if(arr[mid]<=val){
      head = mid + 1;
    } else {
      tail = mid;
    }
  }
  return arr[tail]===val?tail:-1;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章