Рубрики
Без рубрики

Решение: Палиндром связан список

Это является частью серии пояснений решения LeetCode (индекс). Если вам понравилось это решение или Фу … помечены алгоритмами, JavaScript, Java, Python.

Это является частью серии объяснений решения LeetCode ( index ). Если вам понравилось это решение или нашел его полезным, Пожалуйста, как Этот пост и/или УПОТАТЬ Мое решение пост на форумах LeetCode Отказ

Проблема летакода # 234 (Легко): Палиндром связан список

Описание:

( Перейти к : Идея решения Код : JavaScript | Python |. Java |. C ++

Учитывая голова отдельно связанного списка, возврат истинный Если это палиндром.

Примеры:

Вход: голова = [1,2,2,1]
Выход: истинный
Визуальный
Вход: голова = [ 1,2]
Выход: ложный
Визуальный

Ограничения:

  • Количество узлов в списке находится в диапазоне [1, 10^5] .
  • 0.Паль

Идея:

( Перейти к : Описание проблемы Код : JavaScript | Python |. Java |. C ++

Наивный подход здесь будет проходить через связанный список и создать массив его значений, а затем сравнить массив к его обратному, чтобы узнать, если это палиндром. Хотя это достаточно легко для достижения, мы бросили сомнение, чтобы найти подход с Космическая сложность только O (1) при сохранении Сложность времени O (n) Отказ

Единственный способ проверить на палиндром в O (1) Пространство потребует, чтобы мы могли получить доступ к оба узлам для сравнения одновременно, а не хранить значения для более позднего сравнения. Казалось бы, это будет проблемой, поскольку связанный список только способствует путешествию в одном направлении.

Но что, если это не сделало?

Ответ – это обратить вспять половину связанного списка, чтобы иметь Следующий Обратите внимание на предыдущий узел вместо следующего узла. ( Примечание. Мы можем вместо этого добавить атрибут ** Prev *, когда мы повторяем через связанный список, а не перезаписывать Далее на задней половине, но это технически использовать o (n) Extra Пространство , как будто мы создали внешний массив значений узла. *)

Затем первая проблема становится поиском середины связанного списка, чтобы начать наш процесс реверсива. Для этого мы можем посмотреть на Алгоритм обнаружения цикла Флойда Отказ

С Флойдом мы пройдем через связанный список с Два указателя Один из которых движется в два раза быстрее, чем другой. Когда быстро Указатель достигает конца списка, медленно Указатель должен тогда быть в середине. С медленно Теперь посередине мы можем перевернуть заднюю половину списка с помощью другой переменной, чтобы содержать ссылку на предыдущий узел ( Prev ) и трехсторонний обмен. Однако прежде чем мы сделаем это, мы захочем установить Preved.next Так что мы нарушаем обратный цикл и избегайте бесконечного цикла. Как только возвращаемая половина правильно обращается и медленно Еще раз в конце списка мы можем начать быстро снова снова на голова и сравните две половины одновременно, без необходимости дополнительного пространства. Если два указателя когда-либо не согласны, мы можем Вернуть ложь иначе мы можем вернуть правда Если оба указателя достигают среднего успеха.

( Примечание. Этот процесс работает независимо от того, является ли длина связанного списка нечетной или даже, поскольку сравнение остановится, когда медленные достигает узла «тупик». )

Реализация:

Код для всех четырех языков практически идентичен.

Код JavaScript:

( Перейти к : Описание проблемы Идея решения

var isPalindrome = function(head) {
    let slow = head, fast = head, prev, temp
    while (fast && fast.next)
        slow = slow.next, fast = fast.next.next
    prev = slow, slow = slow.next, prev.next = null
    while (slow)
        temp = slow.next, slow.next = prev, prev = slow, slow = temp
    fast = head, slow = prev
    while (slow)
        if (fast.val !== slow.val) return false
        else fast = fast.next, slow = slow.next
    return true
};

Код Python:

( Перейти к : Описание проблемы Идея решения

class Solution:
    def isPalindrome(self, head: ListNode) -> bool:
        slow, fast, prev = head, head, None
        while fast and fast.next:
            slow, fast = slow.next, fast.next.next
        prev, slow, prev.next = slow, slow.next, None
        while slow:
            temp = slow.next
            slow.next, prev, slow = prev, slow, temp
        fast, slow = head, prev
        while slow:
            if fast.val != slow.val: return False
            fast, slow = fast.next, slow.next
        return True

Java код:

( Перейти к : Описание проблемы Идея решения

class Solution {
    public boolean isPalindrome(ListNode head) {
        ListNode slow = head, fast = head, prev, temp;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        prev = slow;
        slow = slow.next;
        prev.next = null;
        while (slow != null) {
            temp = slow.next;
            slow.next = prev;
            prev = slow;
            slow = temp;
        }
        fast = head;
        slow = prev;
        while (slow != null) {
            if (fast.val != slow.val) return false;
            fast = fast.next;
            slow = slow.next;
        }
        return true;
    }
}

C ++ код:

( Перейти к : Описание проблемы Идея решения

class Solution {
public:
    bool isPalindrome(ListNode* head) {
        ListNode *slow = head, *fast = head, *prev, *temp;
        while (fast && fast->next)
            slow = slow->next, fast = fast->next->next;
        prev = slow, slow = slow->next, prev->next = NULL;
        while (slow)
            temp = slow->next, slow->next = prev, prev = slow, slow = temp;
        fast = head, slow = prev;
        while (slow)
            if (fast->val != slow->val) return false;
            else fast = fast->next, slow = slow->next;
        return true;
    }
};

Оригинал: “https://dev.to/seanpgallivan/solution-palindrome-linked-list-5721”