一天一个仿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;
}
posted @ 2022-06-27 00:09  Dont  阅读(49)  评论(0编辑  收藏  举报