题目描述 请判断一个链表是否为回文链表。
示例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("========================="); } }