回文链表

回文链表

这是一道蛮有意思的题目,比较基础的方法就不再说了,我们来说一个比较高级的方法来进行判断。

快慢指针

高级方法就是从链表的中间结点开始,分别向两头进行遍历,于是乎,怎么找到一个链表的中间结点才是一个比较难的地方,这里就使用了快慢指针算法,也就是一个指针每次走两步,一个指针每次只走一步,当快指针停止的时候,慢指针就到达了中间结点的位置。

此时,我们就可以反转后半部分链表,然后分别开始迭代。

反转链表

可以使用递归,也可以使用迭代,不过递归会使用额外的栈空间,所以我们最好使用迭代的方式,迭代的方式也就是我们的三指针算法,即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;
    }
}
Licensed under CC BY-NC-SA 4.0
花有重开日,人无再少年
使用 Hugo 构建
主题 StackJimmy 设计