回文链表的判断

前置知识点:

栈的使用:

 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     } 

 

posted @ 2022-04-08 20:34  jue1e0  阅读(54)  评论(0)    收藏  举报