链表算法面试题---回文链表

题目描述

请判断一个链表是否是回文链表。

进阶要求

仅用O(n)的时间复杂度和O(1)的空间复杂度来实现。

回文链表的定义

1—>2—>3—>2—>1、1—>2—>2—>1这两个都是回文链表

1—>2—>3—>2,不是回文链表

解题思路

我们可以借助其他数据结构来帮助我们实现,比如栈,这样明显简单的多。

解法1

因为栈结构先进后出的特点,我们可以挨个让链表的每一个节点入栈,再出栈比对即可。

    public boolean isPalindrome1(ListNode head) {
    
    
        //定义一个栈
        Stack<ListNode> stack = new Stack<>();
        ListNode node = head;
        //挨个遍历链表的节点,并依次压入栈中
        while (node != null) {
    
    
            stack.push(node);
            node = node.next;
        }
        while (!stack.isEmpty()) {
    
    
            //head不断从头开始遍历,stack不断从尾开始遍历,直到全部遍历结束,如果过程中有不相等的情况,则不是回文链表
            if (head.val == stack.pop().val) {
    
    
                head = head.next;
            } else {
    
    
                return false;
            }
        }
        return true;
    }

考虑进阶的要求,O(1)的空间复杂度,也就意味着不能借助其他的数据结构来实现,这里就需要结合我们之前用到过的关于链表反转,找链表中间节点的内容了

解法2

我们可以先通过快慢指针的方式,在O(1)的空间复杂度下找到链表的中间节点,然后从中间节点开始,反转之后的链表,再从反转链表的头部开始与原链表的头部开始遍历,最终便能判断出是否是回文链表

奇数个节点

在这里插入图片描述

刚好指向中间节点3

在这里插入图片描述

反转后

在这里插入图片描述

开始比对
在这里插入图片描述

在这里插入图片描述

最后直到指向null,元素都相等,则认为是回文链表
在这里插入图片描述

偶数个节点

节点2,2都是中间节点
在这里插入图片描述

慢指针指向第2个中间节点,快指针指向null
在这里插入图片描述

反转后

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
最后直到反转的链表指针指向null,如果值都相等,则认为是回文链表
在这里插入图片描述

 public boolean isPalindrome(ListNode head) {
    
    
        //快慢指针找链表的中间节点
        ListNode fastNode = head;
        ListNode slowNode = head;
        while (fastNode != null && fastNode.next != null) {
    
    
            fastNode = fastNode.next.next;
            slowNode = slowNode.next;
        }
        //从中间节点开始反转链表
        ListNode pre = null;//pre节点为反转链表的头节点
        ListNode next;
        while (slowNode != null) {
    
    
            next = slowNode.next;
            slowNode.next = pre;
            pre = slowNode;
            slowNode = next;
        }
        ListNode right = pre;
        ListNode left = head;
        //两个节点同时开始遍历
        boolean res = true;
        while (right != null) {
    
    
            if (left.val != right.val) {
    
    
                res = false;
                break;
            }
            left = left.next;
            right = right.next;
        }
        //还原链表,把之前反转的链表再反转回来(为了不改变原链表的结构,所以要把破坏的原链表再还原回来)
        ListNode pre2 = null;
        ListNode next2;
        while (pre != null) {
    
    
            next2 = pre.next;
            pre.next = pre2;
            pre2 = pre;
            pre = next2;
        }
        return res;
    }

猜你喜欢

转载自blog.csdn.net/CSDN_WYL2016/article/details/115107877