回文链表的判断
前置知识点:
栈的使用:
1 import java.util.Stack; //引用栈 2 //初始化 3 Stack<Integer> stack = new Stack<Integer>(); 4 //进栈 5 stack.push(Element); 6 //出栈 7 stack.pop(); 8 //取栈顶值(不出栈) 9 stack.peek(); 10 //判断栈是否为空 11 stack.isEmpty()
1.利用栈的方法来实现判断回文链表(需要额外的空间):
1 /* 2 * 方法一: 3 * 通过额外的栈空间来判断是否为回文链表(利用栈后进先出的特点,正好出栈得到链表的逆序) 4 * 但是需要额外的O(n)空间 5 */ 6 @SuppressWarnings("null") 7 public static boolean IsPalinList1(MyLink list) { 8 Stack<Integer> sk = new Stack<>(); 9 Node head = list.head; 10 Node p = head; 11 while (p != null) { 12 sk.push(p.num); 13 p = p.next; 14 } 15 p = head; 16 while (p != null) { 17 if (p.num != sk.peek()) { 18 return false; 19 } 20 sk.pop(); 21 p = p.next; 22 } 23 return true; 24 }
2.不开辟额外空间,直接用本身的特点来实现判断
1 /* 2 * 方法二: 3 * 直接通过链表本身进行判断 4 * 找到链表的中点处,把中点往右的链表翻转,然后分别从最左端和最右端开始逐一比对,直到比对到中间为止 5 */ 6 public static boolean IsPalinList2(MyLink list) { 7 Node head = list.head; 8 if (head == null || head.next == null) { 9 return true; 10 } 11 //用快指针和慢指针来确定中点位置 12 //(当快指针要到末尾时,慢指针处在中点位置(长度为奇偶数分情况讨论,根据题目要求进行微调)) 13 Node fast = head, slow = head; 14 while (fast.next != null && fast.next.next != null) {//是&& 15 fast = fast.next.next; 16 slow = slow.next; 17 } 18 //从slow处的后一个开始翻转链表(以下执行链表反转的操作) 19 Node p = slow; 20 Node q = p.next; 21 slow.next = null;//把中间节点的下一个节点指为null 22 Node r = null; 23 while (q != null) { 24 r = q.next; 25 q.next = p;//不要遗漏 26 p = q; 27 q = r; 28 } 29 r = p;//r指向逆序半链表的头节点(这个位置存着,等下翻转回来需要使用) 30 q = head;//q指向正序半链表的头节点 31 boolean isPalinList = true; 32 while (p != null && q != null) {//p是逆序头节点,q是正序头节点,有一个链表结束就不用继续比了 33 if (p.num != q.num) { 34 isPalinList = false; 35 break; 36 } 37 p = p.next;//从右到中点(不要遗漏) 38 q = q.next;//从左到中点 39 } 40 //把链表恢复原状(即把之前翻转的那部分翻转回来即可) 41 p = r.next;//此时连成的线路为r->p->q(合理复用之前已经申请的变量,避免申请不必要的空间) 42 r.next = null; 43 while (p != null) { 44 q = p.next; 45 p.next = r; 46 r = p; 47 p = q; 48 } 49 return isPalinList; 50 }

浙公网安备 33010602011771号