Глубокое погружение в проблему связанного списка палиндромов на LeetCode.

Введение

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

Обзор проблемы

Задача представляет нам односвязный список и просит определить, является ли этот список палиндромом или нет. Палиндром — это последовательность символов, которая читается как вперед, так и назад. (здесь» ссылка на проблему)

Что такое Палиндром?

Палиндром — это слово, предложение, стих или даже число, которое одинаково читается как вперед, так и назад. Например: гоночный автомобиль; то же самое, если мы читаем это слева или справа.

В Палиндроме много проблем, мы можем применить их к строке или числу. Однако наша сегодняшняя задача применима к односвязному списку, что немного сложнее 😁

Решения

Решений этой проблемы много, вот некоторые из них:

  • Преобразование в массив:
    Перейдите по связанному списку и сохраните значения в массиве, затем используйте два указателя: один в начале, другой в конце (это возможно благодаря индексам). Хороший способ обойти проблему, но это не так и будет большая сложность пространства из-за дополнительной структуры данных (буфера). но это работает 🙋
  • Использование стека:
    Пройдите по связанному списку и поместите все элементы в стек, затем снова пройдите по связанному списку, извлекая элементы из стека.
    Наконец, сравните извлеченные элементы с элементами связанного список. (Хорошо, но то же самое, что и выше в отношении пространственной сложности)

И много-много решений, таких как: перевернуть вторую половину и т. д.

Есть ли оптимизированный способ решения этой проблемы? без буфера? Что ж, я рад сказать ДА!

Интуиция 🧠

Есть ли способ одновременно перемещаться по связанному списку вперед и назад?

Когда я задал себе этот вопрос, мне сразу на ум пришел Возврат. Нормально, но, как?

Используя рекурсию, вы можете перемещаться по связанному списку в прямом направлении, что очень просто. Однако есть ли способ сделать это наоборот? Ответ – ДА!

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

При таком подходе теперь у вас есть два указателя, работающих одновременно, что позволяет сравнивать значения. И это все, что нужно!

Код

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @return {boolean}
 */
var isPalindrome = function(head) {
    let result = true;

    const backtrack = (head2) => {
       if(!head2 || !head) return;

       backtrack(head2.next);
       if(head2.val !== head.val) result = false;

       head = head.next;
    }
    
    backtrack(head);

    return result;
};

Примечание. head и head2 — это два указателя, о которых мы говорили, где head2 — правый, а head — левый.

Кстати, решение идеально соответствует последующей заметке о LeetCode.

Заключение

В этой статье мы рассмотрели рекурсивный подход к решению проблемы связанного списка палиндромов в LeetCode. Используя умную технику рекурсивного сравнения, мы можем эффективно определить, является ли данный связанный список палиндромом или нет.

Это моя первая статья, и я рад услышать ваши отзывы!
Спасибо и всем удачного кодирования!! 💙