Одне з найпопулярніших запитань із структур даних та алгоритму, яке в основному задають на телефонному інтерв'ю.
Одне з найпопулярніших запитань із структур даних та алгоритму, яке в основному задають на телефонному інтерв'ю.
Відповіді:
Обманюючи і роблячи два проходи одночасно, паралельно. Але я не знаю, чи сподобається це рекрутерам.
Це можна зробити за одним пов'язаним списком, з приємною хитрістю. Два вказівники подорожують над списком, один із подвійною швидкістю. Коли швидкий доходить до кінця, інший - на півдорозі.
Якщо це не здвоєний список, ви можете просто порахувати та використати список, але це потребує подвоєння пам’яті в гіршому випадку, і він просто не буде працювати, якщо список занадто великий, щоб зберігати його в пам'яті.
Просте, майже нерозумне рішення - це лише наростити середній вузол кожні два вузли
function middle(start) {
var middle = start
var nextnode = start
var do_increment = false;
while (nextnode.next != null) {
if (do_increment) {
middle = middle.next;
}
do_increment = !do_increment;
nextnode = nextnode.next;
}
return middle;
}
Розвиваючи відповідь Гендрика
Якщо це подвійний список, повторіть його з обох кінців
function middle(start, end) {
do_advance_start = false;
while(start !== end && start && end) {
if (do_advance_start) {
start = start.next
}
else {
end = end.prev
}
do_advance_start = !do_advance_start
}
return (start === end) ? start : null;
}
Дано [1, 2, 3] => 2
1, 3
1, 2
2, 2
Дано [1, 2] => 1
1, 2
1, 1
Дано [1] => 1
Дано [] => null
Створіть динамічний масив, де кожен елемент масиву є вказівником на кожен вузол у списку в порядку проходження, починаючи з початку. Створіть ціле число, ініціалізоване до 1, яке відстежує кількість відвідуваних вами вузлів (з кроком кожного разу, коли ви переходите до нового вузла). Коли ви доходите до кінця, ви знаєте, наскільки великий список, і у вас є впорядкований масив покажчиків на кожен вузол. Нарешті, розділіть розмір списку на 2 (і відніміть 1 для індексації на основі 0) і отримайте вказівник, що знаходиться у цьому індексі масиву; якщо розмір списку непарний, ви можете вибрати, який елемент повернути (я все одно поверну перший).
Ось який-небудь код Java, який отримує крапку (хоча ідея динамічного масиву буде трохи химерною). Я б запропонував C / C ++, але я дуже іржавий у цій галузі.
public Node getMiddleNode(List<Node> nodes){
int size = 1;
//add code to dynamically increase size if at capacity after adding
Node[] pointers = new Node[10];
for (int i = 0; i < nodes.size(); i++){
//remember to dynamically allocate more space if needed
pointers[i] = nodes.get(i);
size++;
}
return pointers[(size - 1)/2];
}
Чи вважається рекурсія більш ніж одним проходом?
Перейдіть список до кінця, передаючи ціле число за посиланням. Зробіть локальну копію цього значення на кожному рівні для подальшого посилання та збільште кількість відліку, переходячи до наступного дзвінка.
На останньому вузлі розділіть рахунок на два і обріжте / підлогу () результат (якщо ви хочете, щоб перший вузол був "серединою", коли є лише два елементи) або округніть (якщо ви хочете, щоб другий вузол був середина"). Використовуйте нульовий або одноосновний індекс відповідним чином.
Відмотуючи, порівняйте кількість посилань з локальною копією (що є номером вузла). Якщо дорівнює, поверніть цей вузол; ще повернути вузол, повернутий з рекурсивного виклику
.
Є й інші способи зробити це; деякі з них можуть бути менш громіздкими (я думав, я бачив, як хтось каже, що він читає його в масив і використовує довжину масиву для визначення середини - кудо). Але, чесно кажучи, хороших відповідей немає, бо це дурне питання інтерв'ю. Номер один, який все ще використовує пов'язані списки ( підтримуюча думка ); По-друге, пошук середнього вузла є довільною академічною вправою, яка не має значення в сценаріях реального життя; По-третє, якби мені дійсно потрібно було знати середній вузол, мій пов'язаний список викрив би кількість вузлів. Зберігати цю властивість легше, ніж витрачати час на проходження всього списку щоразу, коли мені захочеться середній вузол. І нарешті, чотири, кожному інтерв'юєру подобаються чи відкидають різні відповіді - те, що один інтерв'юер вважає струнким, інший назве смішним.
Я майже завжди відповідаю на запитання інтерв'ю ще більше запитань. Якщо у мене з’явиться таке запитання (у мене ніколи не було), я б запитав (1) Що ви зберігаєте в цьому пов'язаному списку, і чи є більш відповідна структура для ефективного доступу до середнього вузла, якщо це дійсно потрібно зробити? ; (2) Які мої обмеження? Я можу зробити це швидше, якщо пам'ять не є проблемою (наприклад, відповідь масиву), але якщо інтерв'юер вважає, що накопичення пам’яті марнотратне, я занурююся. (3) На якій мові я буду розвиватися? Майже в кожній сучасній мові, яку я знаю, є вбудовані класи для роботи з пов’язаними списками, які роблять пересування списку непотрібним - навіщо винаходити щось, що було налаштовано на ефективність розробниками мови?
За допомогою 2 покажчиків. Збільшення по одному при кожній ітерації та інше при кожній другої ітерації. Коли 1-й покажчик вказує на кінець пов'язаного списку, другий вказівник вказує на середній режим пов'язаного списку.