首页 > 其他分享 >图解LeetCode——234. 回文链表

图解LeetCode——234. 回文链表

时间:2023-05-16 12:32:48浏览次数:36  
标签:pre head slow fast next 链表 234 LeetCode

一、题目

给你一个单链表的头节点 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^)/ ~ 「干货分享,每天更新」

标签:pre,head,slow,fast,next,链表,234,LeetCode
From: https://blog.51cto.com/u_15003301/6283430

相关文章

  • 链表排序
    /***Definitionforsingly-linkedlist.*structListNode{*intval;*ListNode*next;*ListNode():val(0),next(nullptr){}*ListNode(intx):val(x),next(nullptr){}*ListNode(intx,ListNode*next):val(x),next(next){}*......
  • Redis数据结构二之SDS和双向链表
    本文首发于公众号:Hunter后端原文链接:Redis数据结构二之SDS和双向链表这一篇笔记介绍一下SDS(simpledynamicstring)和双向链表。以下是本篇笔记目录:SDS常数复杂度获取字符串长度杜绝缓冲区溢出减少修改字符串带来的内存重分配次数二进制安全兼容C字符串函数双向链......
  • LeetCode 101. 对称二叉树
    题目链接:LeetCode101.对称二叉树题意:给你一个二叉树的根节点root,检查它是否轴对称。解题思路:1.递归法采用递归法思路就比较简单,因为要比较二叉树是否是轴对称的,因此就是比较左右子树是否轴对称,因此在遍历的过程中,就是比较左边的左子树与右边的右子树是否相等,以及左......
  • LeetCode 周赛 345(2023/05/14)体验一题多解的算法之美
    本文已收录到AndroidFamily,技术和职场问题,请关注公众号[彭旭锐]提问。往期回顾:LeetCode双周赛第104场·流水的动态规划,铁打的结构化思考周赛概览T1.找出转圈游戏输家(Easy)标签:模拟、计数T2.相邻值的按位异或(Medium)标签:模拟、数学、构造T3.矩阵中移动的最......
  • LeetCode 226. 翻转二叉树
    题目链接:LeetCode226.翻转二叉树题意:给你一棵二叉树的根节点root,翻转这棵二叉树,并返回其根节点。解题思路:对于每一个节点,只需要考虑反转当前节点的左右子树即可,因此只需要考虑遍历顺序,本题中,采用前序和后序遍历都是可以的,但是中序遍历不行,如果采用中序,会将某些节点反转两......
  • LeetCode 94. 二叉树的中序遍历
    题目链接:LeetCode94.二叉树的中序遍历题意:给定一个二叉树的根节点root,返回它的中序遍历。解题思路:对于二叉树的遍历,有递归和非递归两种遍历方式,1.递归遍历**根据“左->根->右”的顺序,直接模拟即可。注意按照递归三部曲(递归的参数和返回值、递归的终止条件、单层......
  • 二刷Leetcode-Days02
    栈和队列:/***232.用栈实现队列*队列的先进先出可以使用两个栈stackIn和stackOut来实现;*出队列前,如果stackOut不为空,表示队列当前值在上一轮已进入stackOut中,还没有被消费掉*若stackOut为空,也就是队列当前值还在stackIn中,为了确保先进先......
  • 剑指 Offer 18. 删除链表的节点
    题目描述:给定单向链表的头指针和一个要删除的节点的值,定义一个函数删除该节点。返回删除后的链表的头节点。     复杂度分析:  时间复杂度O(N):N为链表长度,删除操作平均需循环N/2次,最差N次。  空间复杂度O(1):cur,pre占用常数大小额外空间。class......
  • 2023-05-15 leetcode周赛题
    找出转圈游戏输家mysolution100%passclassSolution:defcircularGameLosers(self,n:int,k:int)->List[int]:seen=set()now_num=1step=1seen.add(1)while1:stepSum=step*ktotal=now_num+stepSumnow_num=tot......
  • 【LeetCode字符串#extra】KMP巩固练习:旋转字符串、字符串轮转
    旋转字符串https://leetcode.cn/problems/rotate-string/给定两个字符串,s和goal。如果在若干次旋转操作之后,s能变成goal,那么返回true。s的旋转操作就是将s最左边的字符移动到最右边。例如,若s='abcde',在旋转一次之后结果就是'bcdea'。示例1:输入:s="......