图解LeetCode——234. 回文链表

简介: 图解LeetCode——234. 回文链表

一、题目

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

二、示例

2.1> 示例 1:

输入】head = [1,2,2,1]

输出】true

2.2> 示例 2:

输入】head = [1,2]

输出】false

提示:

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

进阶:

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

三、解题思路

3.1> 思路1:转存+双指针

根据题目描述,我们需要判断链表是否是回文链表,那么比较容易想到的一种解题方式就是,我们创建一个额外的数组结构,从头节点开始遍历链表,并将其存储到数组结构中。但是对于链表结构来说,只有遍历到最后一个链表,才可以知道整个链表的长度,那么,我们就选择ArrayList来进行额外数据的存储。

在对比过程中,我们通过双指针的方式,分别从首、尾两个位置开始,依次向中心靠拢对比,当方向不同,则表示不是回文链表,否则就是回文链表了。

3.2> 思路2:倒转链表

除了上面的解题方式之外,我们也可以探究一下是否能实现 O(1) 空间复杂度解决此题。那么,由于ListNode单向链表结构,所以只能向一个方向移动,所以为了能够改变遍历方式的话,就可以通过改变next的值来倒转链表。

那么我们就可以将整个链表的一半倒转一下,即:将A——>B倒转为A<——B;那么我们就可以从链表的“中心点”作为开始,分别向两侧进行遍历&对比。那么为题来了,怎么知道那个位置是整个链表的“中心点”呢?此处我们就可以采用快慢指针的方式,即:

慢指针】一次移动一步,即:slow = slow.next

快指针】一次移动两步,即:fast = fast.next.next;

那么当快指针遍历到末尾之后,慢指针就处于了“中心点”范围内了。不过此处还有奇偶数的特殊处理:

偶数长度链表】slow会处于中心点范围(两个节点)中的右侧节点位置;

奇数长度链表】slow会处于中心点位置。

具体操作方式,请见下图所示:

四、代码实现

4.1> 实现1:转存+双指针

class Solution {
    public boolean isPalindrome(ListNode head) {
        List<ListNode> list = new ArrayList();
        while(head != null) {
            list.add(head);
            head = head.next;
        }
        for (int i = 0; i < list.size()/2; i++) 
            if (list.get(i).val != list.get(list.size() - i - 1).val) 
                return false;
        return true;
    }
}

4.2> 实现2:倒转链表

class Solution {
    public boolean isPalindrome(ListNode head) {
        ListNode slow = head, fast = head, pre = null;
        while(fast != null && fast.next != null) {
            ListNode temp = slow.next;
            if (pre != null) slow.next = pre;
            pre = slow;
            slow = temp;
            fast = fast.next.next;
        }
        if (fast != null) slow = slow.next; // 偶数节点
        while (slow != null) {
            if (pre.val != slow.val) return false;
            pre = pre.next;
            slow = slow.next;
        }
        return true;
    }
}

今天的文章内容就这些了:

写作不易,笔者几个小时甚至数天完成的一篇文章,只愿换来您几秒钟的 点赞 & 分享

更多技术干货,欢迎大家关注公众号“爪哇缪斯” ~ \(^o^)/ ~ 「干货分享,每天更新」

相关文章
|
26天前
|
算法
LeetCode第24题两两交换链表中的节点
这篇文章介绍了LeetCode第24题"两两交换链表中的节点"的解题方法,通过使用虚拟节点和前驱节点技巧,实现了链表中相邻节点的交换。
LeetCode第24题两两交换链表中的节点
|
26天前
|
存储 算法
LeetCode第86题分隔链表
文章介绍了LeetCode第86题"分隔链表"的解法,通过创建两个新链表分别存储小于和大于等于给定值x的节点,然后合并这两个链表来解决问题,提供了一种简单易懂且操作原链表的解决方案。
LeetCode第86题分隔链表
|
26天前
|
存储 算法
LeetCode第83题删除排序链表中的重复元素
文章介绍了LeetCode第83题"删除排序链表中的重复元素"的解法,使用双指针技术在原链表上原地删除重复元素,提供了一种时间和空间效率都较高的解决方案。
LeetCode第83题删除排序链表中的重复元素
|
26天前
|
算法
LeetCode第23题合并 K 个升序链表
这篇文章介绍了LeetCode第23题"合并K个升序链表"的解题方法,使用分而治之的思想,通过递归合并链表的方式解决了这个难题。
LeetCode第23题合并 K 个升序链表
|
14天前
|
C++ 索引
leetcode 707.设计链表
本文提供了解决LeetCode 707题"设计链表"的C++实现,包括单链表的节点定义和类方法实现,如添加节点、获取节点值、删除节点等。
|
26天前
|
算法
LeetCode第92题反转链表 II
文章分享了LeetCode第92题"反转链表 II"的解法,通过使用四个指针来记录和更新反转链表段的头部、尾部以及前一个和后一个节点,提供了一种清晰且易于理解的解决方案。
LeetCode第92题反转链表 II
|
26天前
|
算法
LeetCode第21题合并两个有序链表
该文章介绍了 LeetCode 第 21 题合并两个有序链表的解法,通过创建新链表,依次比较两个链表的头节点值,将较小的值插入新链表,直至其中一个链表遍历完,再将另一个链表剩余部分接到新链表后面,实现合并。
LeetCode第21题合并两个有序链表
|
26天前
|
算法
LeetCode第19题删除链表的倒数第 N 个结点
该文章介绍了 LeetCode 第 19 题删除链表的倒数第 N 个结点的解法,通过使用快慢双指针,先将快指针移动 n 步,然后快慢指针一起遍历,直到快指针到达链尾,从而找到倒数第 N 个结点的前一个结点进行删除,同时总结了快慢指针可减少链表遍历次数的特点。
LeetCode第19题删除链表的倒数第 N 个结点
|
28天前
【刷题记录】链表的回文结构
【刷题记录】链表的回文结构
|
1月前
|
算法 Java
LeetCode初级算法题:环形链表+排列硬币+合并两个有序数组java解法
LeetCode初级算法题:环形链表+排列硬币+合并两个有序数组java解法
40 0