题目描述 请判断一个链表是否为回文链表。

示例1:

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

输入: 1->2->2->1 输出: true 进阶:

你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?

首先是节点的定义:

    public static class Node{
        public int value;
        public Node next;

        public Node(int data){
            this.value = data;
        }
    }

方法一

  • 该方法适合于在笔试机试中使用。原理很简单,就是利用一个辅助栈把数据装进去,这样在pop()的时候就是原先的顺序的倒叙输出。空间复杂度O(N)
    //空间复杂度O(N)
    //1.方法一:利用一个栈的后进先出的性质来存储
    public static boolean isPalindrome1(Node head){
        Stack<Node> stack = new Stack<>();
        Node cur = head;
        while (cur!=null){
            stack.push(cur);
            cur = cur.next;
        }
        while (!stack.isEmpty()){
            cur = stack.pop();
            if(cur.value != head.value){
                return false;
            }
            head = head.next;
        }
        return true;
    }

方法二

  • 利用快慢指针,一个一次走两步,一个一次走一步,快指针到头后,慢指针在链表的中间位置。然后从中间位置开始用一个栈开始存储,这时候只需要O(N/2)的空间复杂度。
//空间复杂度O(N/2)
    //利用一个快慢指针,快指针一次走两步,慢指针一次走一步
    //快指针走到头后,慢指针走到链表的中间位置
    //然后用一个辅助栈存储后半部分
    public static boolean isPalindrome2(Node head){
        if(head == null || head.next == null){
            return true;
        }
        Node slow = head.next;
        Node fast = head;

        while (slow.next!=null && slow.next.next != null){
            fast = fast.next.next;
            slow = slow.next;
        }
        Stack<Node> stack = new Stack<>();
        while (slow != null){
            stack.push(slow);
            slow = slow.next;
        }
        while (!stack.isEmpty()){
            if(head.value != stack.pop().value){
                return false;
            }
            head = head.next;
        }
        return true;
    }

方法三

  • 这个方法不需要额外的空间,空间复杂度为O(1),思路还是利用两个快慢指针,其中快指针走到头,慢指针走到中间,这里面也涉及到指针个数的奇数偶数问题如果奇数那就是中间,偶数的话要控制在中间的后面那个开始。然后开始反转右边的链表,其中中间节点的next指向null, 最后的结果也就是左边的一次指向中间节点,右侧的一次指向中间节点,然后从两侧开始遍历,看值是否相同,最后再把右侧的链表反转回去,恢复到初始状态。
//空间复杂度O(1)
    public static boolean isPalindrome3(Node head){
        if(head == null || head.next == null){
            return true;
        }
        Node fast = head;
        Node slow = head;

        while (fast.next!=null && fast.next.next!=null){// find mid node
            fast = fast.next.next; // slow -> mid
            slow = slow.next; // fast -> end
        }
        fast = slow.next; // fast -> 右边部分的第一个节点
        slow.next = null;  // mid.next -> null
        Node n = null;
        while (fast != null){ // 右边部分反转
            n = fast.next; // n -> 保存下一个节点
            fast.next = slow;
            slow = fast; // 继续向下运行
            fast = n; // 继续向下运行
        }
        n = slow; // n -> 最后一个节点
        fast = head; // 左边的第一个节点
        boolean res = true;
        while (slow != null && fast != null){
            if(slow.value != fast.value){
                res = false;
                break;
            }
            slow = slow.next;
            fast = fast.next;
        }
        slow = n.next;
        n.next = null;
        while (slow != null){
            fast = slow.next;
            slow.next = n;
            n = slow;
            slow = fast;
        }
        return res;
    }
    public static void printLinkedList(Node node) {
        System.out.print("Linked List: ");
        while (node != null) {
            System.out.print(node.value + " ");
            node = node.next;
        }
        System.out.println();
    }
  • 最后的全部代码加上主函数测试:
import java.util.Stack;

/**
 * 测试链表是否是回文链表
 * @author zhx
 */
public class IsPalindromeList {


    public static class Node{
        public int value;
        public Node next;

        public Node(int data){
            this.value = data;
        }

    }
    //空间复杂度O(N)
    //1.方法一:利用一个栈的后进先出的性质来存储
    public static boolean isPalindrome1(Node head){
        Stack<Node> stack = new Stack<>();
        Node cur = head;
        while (cur!=null){
            stack.push(cur);
            cur = cur.next;
        }
        while (!stack.isEmpty()){
            cur = stack.pop();
            if(cur.value != head.value){
                return false;
            }
            head = head.next;
        }
        return true;
    }

    //空间复杂度O(N/2)
    //利用一个快慢指针,快指针一次走两步,慢指针一次走一步
    //快指针走到头后,慢指针走到链表的中间位置
    //然后用一个辅助栈存储后半部分
    public static boolean isPalindrome2(Node head){
        if(head == null || head.next == null){
            return true;
        }
        Node slow = head.next;
        Node fast = head;

        while (slow.next!=null && slow.next.next != null){
            fast = fast.next.next;
            slow = slow.next;
        }
        Stack<Node> stack = new Stack<>();
        while (slow != null){
            stack.push(slow);
            slow = slow.next;
        }
        while (!stack.isEmpty()){
            if(head.value != stack.pop().value){
                return false;
            }
            head = head.next;
        }
        return true;
    }

    //空间复杂度O(1)
    public static boolean isPalindrome3(Node head){
        if(head == null || head.next == null){
            return true;
        }
        Node fast = head;
        Node slow = head;

        while (fast.next!=null && fast.next.next!=null){// find mid node
            fast = fast.next.next; // slow -> mid
            slow = slow.next; // fast -> end
        }
        fast = slow.next; // fast -> 右边部分的第一个节点
        slow.next = null;  // mid.next -> null
        Node n = null;
        while (fast != null){ // 右边部分反转
            n = fast.next; // n -> 保存下一个节点
            fast.next = slow;
            slow = fast; // 继续向下运行
            fast = n; // 继续向下运行
        }
        n = slow; // n -> 最后一个节点
        fast = head; // 左边的第一个节点
        boolean res = true;
        while (slow != null && fast != null){
            if(slow.value != fast.value){
                res = false;
                break;
            }
            slow = slow.next;
            fast = fast.next;
        }
        slow = n.next;
        n.next = null;
        while (slow != null){
            fast = slow.next;
            slow.next = n;
            n = slow;
            slow = fast;
        }
        return res;
    }
    public static void printLinkedList(Node node) {
        System.out.print("Linked List: ");
        while (node != null) {
            System.out.print(node.value + " ");
            node = node.next;
        }
        System.out.println();
    }

    public static void main(String[] args) {
        Node head = null;
        printLinkedList(head);
        System.out.print(isPalindrome1(head) + " | ");
        System.out.print(isPalindrome2(head) + " | ");
        System.out.println(isPalindrome3(head) + " | ");
        printLinkedList(head);
        System.out.println("=========================");

        head = new Node(1);
        printLinkedList(head);
        System.out.print(isPalindrome1(head) + " | ");
        System.out.print(isPalindrome2(head) + " | ");
        System.out.println(isPalindrome3(head) + " | ");
        printLinkedList(head);
        System.out.println("=========================");

        head = new Node(1);
        head.next = new Node(2);
        printLinkedList(head);
        System.out.print(isPalindrome1(head) + " | ");
        System.out.print(isPalindrome2(head) + " | ");
        System.out.println(isPalindrome3(head) + " | ");
        printLinkedList(head);
        System.out.println("=========================");

        head = new Node(1);
        head.next = new Node(1);
        printLinkedList(head);
        System.out.print(isPalindrome1(head) + " | ");
        System.out.print(isPalindrome2(head) + " | ");
        System.out.println(isPalindrome3(head) + " | ");
        printLinkedList(head);
        System.out.println("=========================");

        head = new Node(1);
        head.next = new Node(2);
        head.next.next = new Node(3);
        printLinkedList(head);
        System.out.print(isPalindrome1(head) + " | ");
        System.out.print(isPalindrome2(head) + " | ");
        System.out.println(isPalindrome3(head) + " | ");
        printLinkedList(head);
        System.out.println("=========================");

        head = new Node(1);
        head.next = new Node(2);
        head.next.next = new Node(1);
        printLinkedList(head);
        System.out.print(isPalindrome1(head) + " | ");
        System.out.print(isPalindrome2(head) + " | ");
        System.out.println(isPalindrome3(head) + " | ");
        printLinkedList(head);
        System.out.println("=========================");

        head = new Node(1);
        head.next = new Node(2);
        head.next.next = new Node(3);
        head.next.next.next = new Node(1);
        printLinkedList(head);
        System.out.print(isPalindrome1(head) + " | ");
        System.out.print(isPalindrome2(head) + " | ");
        System.out.println(isPalindrome3(head) + " | ");
        printLinkedList(head);
        System.out.println("=========================");

        head = new Node(1);
        head.next = new Node(2);
        head.next.next = new Node(2);
        head.next.next.next = new Node(1);
        printLinkedList(head);
        System.out.print(isPalindrome1(head) + " | ");
        System.out.print(isPalindrome2(head) + " | ");
        System.out.println(isPalindrome3(head) + " | ");
        printLinkedList(head);
        System.out.println("=========================");

        head = new Node(1);
        head.next = new Node(2);
        head.next.next = new Node(3);
        head.next.next.next = new Node(2);
        head.next.next.next.next = new Node(1);
        printLinkedList(head);
        System.out.print(isPalindrome1(head) + " | ");
        System.out.print(isPalindrome2(head) + " | ");
        System.out.println(isPalindrome3(head) + " | ");
        printLinkedList(head);
        System.out.println("=========================");
    }
}