【算法】判断一个无环单链表是否为回文链表

回文是指不管是顺序读还是逆序读,读出来的都是一样效果。例如 12321 和1221 都是一个回文序列

判断一个单链表是否是回文链表可以构建一个栈,把链表结点依次入栈,然后再出栈与链表对比即可。这种方法是比较容易想到的,但额外空间复杂度是O(N)。

public static boolean isPalindrome(Node head) {
    Stack<Node> stack = new Stack<>();
    Node cur = head;
    while (cur != null) { //链表结点依次入栈
        stack.push(cur);
        cur = cur.next;
    }
    while (head != null) { //出栈并比较
        if (head.value != stack.pop().value) {
            return false;
        }
        head = head.next;
    }
    return true;
}

若要求额外空间复杂度是O(1)呢?

可以将链表的右半部分逆序,并连到中间结点上,然后再从两头开始依次对比从而判断是否为回文。

image-20220119003213206

public static boolean isPalindrome(Node head) {
    if (head == null || head.next == null) {
        return true;
    }
    
    Node n1 = head;
    Node n2 = head;
    while (n2.next != null && n2.next.next != null) { //通过快慢指针找中间结点
        n1 = n1.next;
        n2 = n2.next.next;
    }
    
    n2 = n1.next; //n2指向右半部分的第一个结点
    n1.next = null; //中间结点指向空
    Node n3 = null;
    while (n2 != null) { //将右半部分逆序
        n3 = n2.next;
        n2.next = n1;
        n1 = n2;
        n2 = n3;
    }
    
    n3 = n1; //保存最后一个结点
    n2 = head;
    boolean res = true;
    while (n1 != null && n2 != null) { //检查是否回文
        if (n1.value != n2.value) {
            res = false;
            break;
        }
        n1 = n1.next;
        n2 = n2.next;
    }
    
    n1 = n3.next;
    n3.next = null;
    while (n1 != null) { //恢复链表
        n2 = n1.next;
        n1.next = n3;
        n3 = n1;
        n1 = n2;
    }
    
    return res;
}
posted @ 2022-01-19 00:35  hzyuan  阅读(37)  评论(0)    收藏  举报