题目

判断一个链表是否为回文结构 【题目】 给定一个链表的头节点head,请判断该链表是否为回文结构。 例如: 1->2->1,返回true。
1->2->2->1,返回true。 15->6->15,返回true。 1->2->3,返回false。
进阶: 如果链表长度为N,时间复杂度达到O(N),额外空间复杂度达到O(1)。

1.借助栈实现

1.1 思路

栈是一个先进后出的结果,如果一个链表是回文的话 那么势必 出栈的val 等于 正序的val
时间复杂度:O(n)
空间复杂度:O(n)

1.2 code

public boolean isPalindrome(ListNode head) {
        if(head == null){
            return true;
        }
        Stack<ListNode> stack = new Stack<>();
        ListNode cur = head;
        while(cur != null){
            stack.push(cur);
            cur = cur.next;
        }

        while(head!=null){
            if(head.val != stack.pop().val){
                return false;
            }
            head = head.next;
        }
        return true;
    }
2.快慢指针+栈

2.1 思路

快慢指针就是定义两个节点都指向head节点 fast节点每次走两步,slow节点每次走一步。当fast节点走到尾部,slow节点必定在链表的中间位置(如果是奇数个 在中间 ,偶数的话在中间位置的左边)。
将后半部分的节点依次push到栈中。然后依次比较栈中pop的元素和head节点依序比较,如果相同,为回文结构,否则的话,不是回文结构。
时间复杂度:O(n)
空间复杂度:O(n/2)

2.2 code

//2.快慢指针+栈 
    public boolean isPalindrome(ListNode head) {
        if(head == null || head.next == null){
            return true;
        }
        ListNode fastNode = head;
        ListNode slowNode = head.next;
        //快慢指针
        while(fastNode.next != null && fastNode.next.next != null){
            slowNode = slowNode.next;
            fastNode = fastNode.next.next;
        }
        // 剩余的一般节点添加进栈中
        Stack<ListNode> stack = new Stack<>();
        while(slowNode != null){
            stack.push(slowNode);
            slowNode = slowNode.next;
        }

        //比较stack 和 head 前一半是否相同
        while(!stack.isEmpty()){
            if(head.val != stack.pop().val){
                return false;
            }
            head = head.next;
        }
        return true;
    }
3.快慢指针+逆序链表

3.1 思路

通过第一种和第二种 虽然space逐渐减半,但是对于大数据量的链表,如果能将空间复杂度减到O(1)无疑是最优的答案,因此,先用快慢指针找到mid点 然后将mid之后的链表反转和mid之前的链表元素进行比较,如果不相等 存储res结果退出,否则的话 比较,最后 将逆序的部分在逆序回来。
时间复杂度:O(n)
空间复杂度:O(1)

3.2 code

//反转 比较 反转 time O(n) space : O(1)
    public boolean isPalindrome3(ListNode head) {
        if(head == null || head.next == null) {
            return true;
        }
        ListNode n1 = head;
        ListNode n2 = head;
        //快慢指针
        while(n2.next!=null && n2.next.next!=null){
            n1 = n1.next;
            n2 = n2.next.next;
        }
        //后半部分链表反转
        n2 = n1.next;
        n1.next = null;
        ListNode 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.val!=n2.val){
                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;
    }