hot100 234.回文链表

思路:

1.先考虑怎么判断一个字符串是不是回文字符串。可以从最左最右开始,比较第一个字母和最后一个字母是不是一样的,如果第一个字母和最后一个字母是一样的,那么就继续比较第二个字母和倒数第二个字母,以此类推。

2.如何快速找到链表的最后一个节点、倒数第二个节点、倒数第三个节点......?

3.首先可以找到链表的中间节点:

(1)如果链表有奇数个节点,就找正中间的节点。

(2)如果链表有偶数个节点,就找正中间右边的节点。

4.然后把中间节点到链表末尾反转,如上图所示,反转后得到链表6->5->4,其头节点记作head2,这样就能从head2开始,依次访问原链表的最后一个节点、倒数第二个节点、倒数第三个节点...。

5.最后,同时遍历head和head2这两个链表,每次循环判断head.val是否等于head2.val,若不相等,则返回false。循环直到head2链表遍历结束,如果循环中没有返回false,则说明链表是回文的,返回true。

6.注意:

(1)第一张图中的2->3,在反转链表后,并不会断开。第一张图反转链表后,我们得到了两条链表:一条是1->2->3,另一条是5->4->3。

(2)第二张图中的3->4,在反转链表后,并不会断开。第二张图反转链表后,我们得到了两条链表:一条是1->2->3->4,另一条是6->5->4。这意味着代码在写循环的时候,循环条件要判断head2是否为空而不是head是否为空,否则会错误地多循环一次,导致访问head2.val出现空指针异常。

7.问:为什么不反转整个链表,这样也可以访问原链表的最后一个节点、倒数第二个节点、倒数第三个节点......?

答:

因为还要从head开始遍历链表,访问原链表的第一个节点、第二个节点、第三个节点......。如果反转整个链表,那么链表前半段的结构就被破坏了。

8.复杂度分析:

(1)时间复杂度:O(n),其中n是链表的长度(节点个数)。

(2)空间复杂度:O(1)。

附代码:

java 复制代码
class Solution {
    public boolean isPalindrome(ListNode head) {
        ListNode mid = middleNode(head);
        ListNode head2 = reverseList(mid);
        while(head2 != null){
            if(head.val != head2.val){ // 不是回文链表
                return false;
            }
            head = head.next;
            head2 = head2.next;
        }
        return true;
    }

    //求链表的中间节点
    //快慢指针法,对于无环链表,可让快指针每次走两步,慢指针每次走一步,当快指针走到结尾处时慢指针到达中间节点
    private ListNode middleNode(ListNode head){
        ListNode slow = head;
        ListNode fast = head;
        while(fast != null && fast.next != null){
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }
    //反转链表
    private ListNode reverseList(ListNode head){
        ListNode pre = null;
        ListNode cur = head;
        while(cur != null){
            ListNode tmp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = tmp;
        }
        return pre;
    }
}
相关推荐
小江的记录本10 小时前
【Java基础】泛型:泛型擦除、通配符、上下界限定(附《思维导图》+《面试高频考点清单》)
java·数据结构·后端·mysql·spring·面试·职场和发展
落羽的落羽11 小时前
【算法札记】练习 | Week4
linux·服务器·数据结构·c++·人工智能·算法·动态规划
萑澈12 小时前
算法竞赛入门:C++ STL核心用法与时空复杂度速查手册
数据结构·c++·算法·stl
yuannl1013 小时前
数据结构----二叉排序树(ai修改版)
数据结构
iiiiyu14 小时前
集合进阶(Map集合)
java·大数据·开发语言·数据结构·编程语言
小江的记录本14 小时前
【Java基础】核心关键字:final、static、volatile、synchronized、transient(附《思维导图》+《面试高频考点清单》)
java·前端·数据结构·后端·ai·面试·ai编程
go不是csgo15 小时前
两个Redis数据结构搞定签到和UV统计:Bitmap与HyperLogLog实战
数据结构·redis·uv
悠仁さん15 小时前
数据结构 栈与队
数据结构
Plan-C-16 小时前
二叉树的遍历
java·数据结构·算法
历程里程碑16 小时前
54 深入解析poll多路复用技术
java·linux·服务器·开发语言·前端·数据结构·c++