回文链表
这是一道蛮有意思的题目,比较基础的方法就不再说了,我们来说一个比较高级的方法来进行判断。
快慢指针
高级方法就是从链表的中间结点开始,分别向两头进行遍历,于是乎,怎么找到一个链表的中间结点才是一个比较难的地方,这里就使用了快慢指针算法,也就是一个指针每次走两步,一个指针每次只走一步,当快指针停止的时候,慢指针就到达了中间结点的位置。
此时,我们就可以反转后半部分链表,然后分别开始迭代。
反转链表
可以使用递归,也可以使用迭代,不过递归会使用额外的栈空间,所以我们最好使用迭代的方式,迭代的方式也就是我们的三指针算法,即prev,pCur,pNext这三个辅助指针
1
2
3
4
5
6
7
8
9
10
11
|
public ListNode reverseList(ListNode node) {
ListNode prev = null;
ListNode pCur = node;
while (pCur != null) {
ListNode pNext = pCur.next;
pCur.next = prev;
prev = pCur;
pCur = pNext;
}
return prev;
}
|
快慢指针搜索
记住核心的算法步骤即可,快指针每次走两步,慢指针每次只走一步。
1
2
3
4
5
6
7
8
9
|
public ListNode getFirstOfEnd(ListNode node) {
ListNode fast = node;
ListNode slow = node;
while (fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
|
算法实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public boolean isPalindrome(ListNode head) {
// 得到第一段的结尾
ListNode pCur = head;
ListNode endOfFirst = getFirstEnd(pCur);
// System.out.println(endOfFirst.val);
// 逆转后面的一段
ListNode secondOfHead = reverseList(endOfFirst.next);
ListNode p2 = secondOfHead;
boolean result = true;
while (result && p2 != null) {
if (pCur.val != p2.val) {
result = false;
}
pCur = pCur.next;
p2 = p2.next;
}
// 反转回来
endOfFirst.next = reverseList(secondOfHead);
return result;
}
private ListNode getFirstEnd(ListNode node) {
ListNode fast = node;
ListNode slow = node;
while (fast.next != null && fast.next.next != null) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
private ListNode reverseList(ListNode node) {
ListNode prev = null;
ListNode cur = node;
while (cur != null) {
ListNode pNext = cur.next;
cur.next = prev;
prev = cur;
cur = pNext;
}
return prev;
}
}
|