牛客网新出了一个算法速刷 TOP101 题单,按照标签进行分类刷题,涵盖了链表、二分查找、排序、二叉树、堆、栈、队列、哈希、递归、回溯算法、动态规划、字符串、双指针、贪心算法、模拟算法等多个高频知识考点,准备校招、临时突击算法面试的同学可以根据这份题单进行系统的刷题。

题单地址:https://www.nowcoder.com/link/pc_kol_wsx

一、题目描述

给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false

示例 1:

img

输入:head = [1,2,2,1]
输出:true

示例 2:

img

输入:head = [1,2]
输出:false

提示:

  • 链表中节点数目在范围[1, 105]
  • 0 <= Node.val <= 9

进阶:你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?

二、题目解析

1、使用快慢指针寻找出单链表的中间结点来,通过这个中间结点,可以把单链表划分为两个部分。

2、左部分包含了中间结点,右部分不包含中间结点。

3、使用迭代法反转右边部分。

4、设置两个指针,一个指向链表的头节点,一个指向反转成功之后的右部分的头结点。

5、让这两个指针向内部移动,对比它们指向的结点值,如果发现结点值相同,继续向内移动,如果不相同,则可以直接返回 false。

三、参考代码

class Solution {
    public boolean isPalindrome(ListNode head) {

        // 找到前半部分链表的尾节点并反转后半部分链表
        ListNode leftEnd =  middleNode(head);

        // 反转链表
        ListNode rigthStart =  reverseList(leftEnd.next);

        // 判断是否回文
        ListNode a = head;

        ListNode b = rigthStart;

        boolean result = true;

        while (result && b != null) {
            if (a.val != b.val) {

                result = false;

            }

            a = a.next;

            b = b.next;

        }        

        return result;
    }


    // 迭代方法进行反转链表
    private ListNode reverseList(ListNode head) {
        ListNode prev = null;
        ListNode curr = head;
        while (curr != null) {
            ListNode nextTemp = curr.next;
            curr.next = prev;
            prev = curr;
            curr = nextTemp;
        }
        return prev;
    }

    // 获取链表的中间节点
    private ListNode middleNode(ListNode head) {

        // 设置两个指针,一开始都指向链表的头节点
        ListNode slow = head;

        ListNode fast = head;

        // 接下来,让这两个指针向前移动
        // 如果可以移动,那么就会让快指针每次移动两步,慢指针每次移动一步
        // 而快指针可以移动两步的前提就是当前节点不为空,同时下一节点也不为空
        // 这样才能保证 fast.next 有值、fast.next.next 有值
        while(fast.next != null && fast.next.next != null){

            // 慢指针每次移动一步
            slow = slow.next;

            // 快指针每次移动两步
            fast = fast.next.next;
        }

        // 最后,slow 指向的就是中间节点
        return slow;

    }
}