拖了一週了,上週一直在忙(其實是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;
}