判断一个链表是否是回文结构
【题目】给定一个单链表的头节点head,请判断该链表是否为回文结构。 【例子】1->2->1,返回true;1->2->2->1,返回true;15->6->15,返回true;1->2->3,返回false。 【例子】如果链表长度为N,时间复杂度达到0(N),额外空间复杂度达到0(1)。
代码
package Algorithms.linkedNode; /** * @author : zhang * @version : 1.0 * @date : Create in 2021/8/10 * @description : */ import java.util.Stack; public class IsPalindromeList { public static class Node { public int value; public Node next; public Node(int data) { this.value = data; } } // need n extra space 笔试用此种方法 public static boolean isPalindrome1(Node head) { Stack<Integer> stack = new Stack<>(); Node cur = head; while (cur!=null){ stack.push(cur.value); cur = cur.next; } while (head!=null){ if (head.value!=stack.pop()){ return false; } head = head.next; } return true; } // need n/2 extra space 快慢指针:cur走1步,right走两步 public static boolean isPalindrome2(Node head) { if (head == null || head.next == null) { return true; } Node cur = head; Node right = head.next; while (cur.next!=null && cur.next.next!=null){ cur = cur.next; right = right.next; } Stack<Integer> stack = new Stack<>(); while (right!=null){ stack.push(right.value); right = right.next; } while(!stack.isEmpty()){ if (head.value!=stack.pop()){ return false; } head = head.next; } return true; } // need O(1) extra space 面试用此方法回答(使用有限的几个变量) //过程举例:将 1 -> 2 -> 3 -> 2 -> 1 变为:1 -> 2 -> 3 <- 2 <- 1 进行比较 //最后再变为1 -> 2 -> 3 -> 2 -> 1返回true //过程: //1、使用快慢指针:慢指针n1每次走1步,快指针n2每次走2步,快指针n2走到结尾的时候,慢指针n1来到中间位置 //2、n1之后节点逆序(指向mid,3 <- 2 <- 1),逆序之后n1来到重点位置,n2为null //3、判断是否回文(左右两边进行比较) //4、后半部分再次进行逆序,保持原始结构 public static boolean isPalindrome3(Node head) { if (head == null || head.next == null) { return true; } //1、快慢指针 Node n1 = head; Node n2 = head; while (n2.next != null && n2.next.next != null) { // find mid node n1 = n1.next; // n1 -> mid n2 = n2.next.next; // n2 -> end } n2 = n1.next; // n2 -> right part first node n1.next = null; // mid.next -> null Node n3 = null; //2、逆序 while (n2 != null) { // right part convert n3 = n2.next; // n3 -> save next node n2.next = n1; // next of right node convert n1 = n2; // n1 move n2 = n3; // n2 move } //3、判断是否回文 n3 = n1; // n3 -> save last node n2 = head;// n2 -> left first node boolean res = true; while (n1 != null && n2 != null) { // check palindrome if (n1.value != n2.value) { res = false; break; } n1 = n1.next; // left to mid n2 = n2.next; // right to mid } //4、后半部分再次进行逆序,保持原始结构 n1 = n3.next; n3.next = null; // while (n1 != null) { // recover list n2 = n1.next; n1.next = n3; n3 = n1; n1 = n2; } 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 = 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); } } /** * Linked List: 1 2 3 2 1 * true | true | true | * Linked List: 1 2 3 2 1 */