В продолжение прошлой недели, проблема этой недели на торте интервью только что дала мне возможность снова просмотреть бинарный поиск. Состояния подсказки, переданные в функцию, представляют собой массив слов, взятых из словаря, который был открыт где-то недалеко от центра. Соответственно, первые слова в массиве начинаются с буквы где-то в середине алфавита. Затем человек, пытающийся улучшить свой словарный запас, продолжает листать, пока не дойдет до конца, после чего он поворачивается к началу и просматривает его, пока не вернется к тому, с чего начал.

Нас просят написать функцию, принимающую один такой массив и возвращающую индекс точки перегиба, точки, в которой очевидно, что детектив словаря начал снова с самого начала. В качестве примера приведен следующий массив с точкой перегиба, находящейся в «асимптоте»:

const words = [
'ptolemaic',
'retrograde',
'supplant',
'undulate',
'xenoepist',
'asymptote',
'babka',
'banoffee',
'engender',
'karpatka',
'othellolagkage',
]

Это псевдокод для моего подхода к проблеме:

//   start at the middle; check to see if the inflection point is at the median
// the value of the first letter of the word at the median should be less than the value of the first letter of the next word
// if it is not, then the median is the inflection point
//   if the median is not the inflection point, go forward or backward depending on how close to the inflection point you are and
//   check the median again until you find it

И это мое решение:

function rotationPoint (words) {
let start = 0;
let end = words.length - 1;
let median;
while (start <= end){
median = parseInt((start + end) / 2);
if ((words[median][0] < words[median - 1][0])) {
return median;
}
else if (words[median][0]< words[0][0]) {
end = median - 1;
}
else {
start = median + 1;
}
}
}

Если медиана не является точкой перегиба, то я проверяю, не меньше ли первая буква слова там, чем значение первой буквы первого слова в массиве. Если это так, то это означает, что точка перегиба находится раньше в массиве; таким образом, конец теперь перемещается на одну позицию перед текущей медианой. В противном случае точка перегиба находится дальше по линии с правой стороны массива, поэтому начало становится медианой + 1.

Примечание об использовании операторов «больше» и «меньше» с буквами. JavaScript позволяет нам проводить это сравнение без преобразования символов в числа. Однако, если бы мы захотели, мы могли бы использовать вместо этого .charCodeAt(). Например,

words[median].charCodeAt(0) < words[median-1].charCodeAt(0)

работает так же, как

words[median][0] < words[median - 1][0]


Цикл while выполняется до тех пор, пока либо не будет возвращен индекс точки перегиба, либо начальное значение не станет больше, чем значение конечной точки (см. мой последний пост в блоге для объяснения этого).

Хотя я ее не знаю, это профиль на Github человека, чей код на LeetCode помог мне лучше понять Binary Search: https://github.com/yuyuhhh.

Спасибо! Ты заслуживаешь кусок пирога.