fucking-algorithm icon indicating copy to clipboard operation
fucking-algorithm copied to clipboard

如何高效判断回文链表 :: labuladong的算法小抄

Open utterances-bot opened this issue 3 years ago • 9 comments

如何高效判断回文链表 :: labuladong的算法小抄

https://labuladong.gitee.io/algo/2/17/18/

utterances-bot avatar May 20 '21 09:05 utterances-bot

while (right != null) { 这里还要判断一下 left!=null

AVAL-NIX avatar May 20 '21 09:05 AVAL-NIX

if (fast != null) slow = slow.next;

这里要判断slow.next != null ,如果输入只有一个元素,可能会出现slow.next = null 的情况,导致slow.val 出错。

JewinH avatar Jun 26 '21 09:06 JewinH

赞赞赞!写的太好了

Yuyan9618 avatar Aug 18 '21 02:08 Yuyan9618

下面这个不判断,好像也行。

if (fast != null)
    slow = slow.next;

1-2- 3-2-1-null 反转后的两条分别是 1-2-3-null 1-2-3-null 不加也行的。

keeleys avatar Sep 07 '21 06:09 keeleys

public boolean isPalindrome2(ListNode head) {
        // 先通过双指针找到链表的中点
        ListNode slow, fast;
        slow = fast = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        // slow 指向链表中点
        // 如果fast指针没有指向null, 说明链表长度为奇数, slow还要再前进一步
        if (fast != null) {
            slow = slow.next;
        }

        // 用于恢复链表结构的指针
        ListNode p, q;

        // 从slow开始反转后面的链表, 开始比较回文串
        ListNode left = head;
        ListNode right = reverse(slow);
        p = left; q = right;
        while (right != null) {
            if (left.val != right.val) {
                return false;
            }
            p = left;
            left = left.next;
            right = right.next;
        }

        p.next = reverse(q);
        return true;
    }

jungle8884 avatar Sep 26 '21 02:09 jungle8884

请问如果要恢复链表结构,如何得到p,q的位置?

SharkLJ avatar Oct 23 '21 00:10 SharkLJ

请问如果要恢复链表结构,如何得到p,q的位置?

仅供参考

 public boolean isPalindrome(ListNode head) {
        ListNode fast = head, slow = head;
        // 恢复链表结构
        ListNode p = null, q = null;
        // slow 指向链表中点
        while (fast != null && fast.next != null) {
            p = slow;
            slow = slow.next;
            fast = fast.next.next;
        }
        // 说明链表有奇数个节点,slow需要再进一步
        if (fast != null) {
            p = slow;
            slow = slow.next;
        }
        ListNode left = head;
        // 局部反转链表
        ListNode right = reverse(slow);
        q = right;
        while (right != null) {
            // 判断是否为回文串
            if (left.val != right.val) {
                // 当链表没有节点或只有一个节点时,不需要恢复链表
                if (p != null && p != q) {
                    p.next = reverse(q);
                }
                return false;
            }
            left = left.next;
            right = right.next;
        }
        if (p != null && p != q) {
            p.next = reverse(q);
        }
        return true;
    }

tt110617 avatar Jan 22 '22 03:01 tt110617

简单易懂,赞!

gcdd1993 avatar Jan 29 '22 09:01 gcdd1993

捉个小虫,最后恢复后一半链表的时候不需要更改前一半的最后一个node。也就是相对于q.next = reverse(headOfReversedSecondHalf),直接使用reverse(headOfReversedSecondHalf)。 根据你画的反转过的链表图,其实前一半最后一个节点一直指向第二半的第一个节点。

1→2→3→4→3→2→1

↓

1→2→3→4→3←2←1

所以最后只需要再次把后一半链表反转足矣

boolean isPalindrome(ListNode head) {
    ListNode slow, fast;
    slow = fast = head;
    while (fast != null && fast.next != null) {
        slow = slow.next;
        fast = fast.next.next;
    }
    
    if (fast != null)
        slow = slow.next;
    
    ListNode left = head;
    //----
    ListNode headOfReversedSecondHalf = reverse(slow);
    //----
    ListNode right = headOfReversedSecondHalf;
    while (right != null) {
        if (left.val != right.val)
            return false;
        left = left.next;
        right = right.next;
    }

    //----
    // recover 2nd half
    reverse(headOfReversedSecondHalf);
    //----

    return true;
}

Goolloo avatar Jan 30 '22 05:01 Goolloo