算法-判断链表是否为回文链表

算法-判断链表是否为回文链表

1、判断链表是否为回文链表

题目来源:Leetcode234,是一道easy题。

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

示例 1:

输入: 1->2
输出: false
示例 2:

输入: 1->2->2->1
输出: true
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/palindrome-linked-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

我们知道单向链表只有指向后面的指针,所以不能像数组那样,从两端向中间遍历,不过。

很自然的,我们可以利用栈的性质来存储链表,然后弹出和原链表比较,时空复杂度为N/N

    /**
     * 用栈性质实现
     * @param head
     * @return
     */
    public boolean isPalindrome(ListNode head){
    
    
        Stack<ListNode> stack=new Stack<>();
        ListNode curr=head;
        while (curr!=null){
    
    
            stack.push(curr);
            curr=curr.next;
        }
        while (head!=null){
    
    
            if(head.val!=stack.pop().val){
    
    
                return false;
            }
            head=head.next;
        }
        return true;
    }

然而,面试官一般不会就这样放过我们,让我们在时空复杂度上进行优化。从时间复杂度上来说,已经做到了2*N(入栈出栈),这题目也不可能用二分法优化的log(n),所以,我们可以从空间复杂度上入手。

回文字符的定义是什么?围绕着中点对称,由此,我们可以先找到链表的中点,把链表分为两部分,这两部分是逆序排列的,于是,我们可以将前一段链表反转,然后和后一段链表进行比较!

涉及到的知识
1、链表反转问题,在我之前发的文章中有非常详细的解释,这里就不多说了。
2、寻找链表中点问题,思路是快慢指针,在前面文章也有解读

    /**
     * 解题思路:在找中点的时候对前半部分进行翻转,时空复杂度为n和1
     * @param head
     * @return
     */
    public boolean isPalindrome(ListNode head){
    
    
        if(head==null||head.next==null){
    
    
            return true;
        }
        ListNode quick=head;
        ListNode slow=head;

        ListNode prev=null;
        ListNode curr=head;
        while (quick!=null&&quick.next!=null){
    
    
            ListNode temp=slow.next;
            quick=quick.next.next;
            slow=slow.next;
            curr.next=prev;
            prev=curr;
            curr=temp;
        }
        if(quick!=null){
    
    //奇数个元素,跳过中间节点
            slow=slow.next;
        }
        ListNode frontNode=prev;
        while (frontNode!=null){
    
    
            if(frontNode.val!=slow.val){
    
    
                return false;
            }
            frontNode=frontNode.next;
            slow=slow.next;
        }
        return true;
    }

值得注意的是,在寻找链表中点的过程中,如果链表长度为偶数,慢指针最终指向中点靠后的那个节点,快指针为null,如果链表长度为奇数,那么慢指针最终指向正中间的节点,因此,在比较之前需要指向自己的后一个节点。

猜你喜欢

转载自blog.csdn.net/qq_23594799/article/details/106989126