【LeetCode】No.234. Palindrome Linked List -- Java Version

126 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

题目链接: leetcode.com/problems/pa…

1. 题目介绍

Given the head of a singly linked list, return true if it is a palindrome. 【Translate】:给定单链表的头部,如果是回文则返回真

测试用例: 测试用例 约束: 约束 期望: 在这里插入图片描述

2. 题解

2.1 利用栈来辅助存储并比较

  该方法就是通过使用栈来存储Node中的数据,然后依次出栈并与Node比较,缺点是需要N个额外的空间,且用时较长,但思想和语句简单,属于枚举的思想。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public boolean isPalindrome(ListNode head) {
        Stack<ListNode> stack = new Stack<ListNode>();
        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;
    }
}

case1

2.2 使用快慢指针确定好奇偶的中点

  该方法使用快慢指针先确定好奇偶的中点,然后让中点后的右半部分入栈,然后再依次与head比较,这样做就可以节省一半需要操作的空间和时间。

 public boolean isPalindrome(ListNode head) {
        if (head == null || head.next == null) {
			return true;
		}
        ListNode right = head.next;
        ListNode cur = head;
        
        // 先让right来到中点
        while(cur.next != null && cur.next.next != null){
            right = right.next;
            cur = cur.next.next;
        }
        
        Stack<ListNode> stack = new Stack<ListNode>();
        
        // 将右半部分压入栈中
        while(right != null){
            stack.push(right);
            right = right.next;
        }
        
        while(!stack.isEmpty()){
            if(head.val != stack.pop().val){
                return false;
            }
            head = head.next;
        }
        return true;
    }

case2

2.3 不用堆栈的O(1)的方法

  首先我们还是通过快慢指针先找到中点,通过快慢指针使得n1为中点,此时让n2变成中点的下一个点,然后让中点指向null,然后定义n3,通过n1,n2,n3的配合依次交换,反转右半部分链表的指向,最后验证完之后,不要忘了把改变的指向恢复成原样。

    public boolean isPalindrome3(ListNode head) {
        if (head == null || head.next == null) {
            return true;
        }
        
		ListNode n1 = head;
        ListNode n2 = head;
        
        // 让n1来到中点
        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;
        }
        
        n2 = head;  // n2指向头节点
        n3 = n1;  // n3指向最后一个节点
        
        boolean res = true;
        
        while(n2 != null && n3 != null){  // 这里为什么没用(n2.next), 这是为了照顾只有两个数据的情况
            if(n2.val != n3.val){
                res = false;
                break;
            }
            n2 = n2.next;
            n3 = n3.next;
        }
        
        n3 = n1;
        n2 = n3.next;
        n3.next = null;
        
        // 将反转的右半边链表复原
        while(n2 != null){
            n1 = n2.next;
            n2.next = n3;
            n3 = n1;
            n2 = n1;
        }
        return res;
    }

case3

3. 可参考

[1] while中continue break return各自的作用

[2] Java isEmpty()方法:判断字符串是否为空

[3] 左程云 -- 链表相关面试题(Video)