• 回文链表判断


    回文字符串和数组我们会经常遇到,今天讲一个相关问题,叫回文链表,还是和以前一样,先把代码提上来。

    1. // need O(1) extra space
    2. public static boolean isPalindrome3(Node head) {
    3. if (head == null || head.next == null) {
    4. return true;
    5. }
    6. Node n1 = head;
    7. Node n2 = head;
    8. while (n2.next != null && n2.next.next != null) { // find mid node
    9. n1 = n1.next; // n1 -> mid
    10. n2 = n2.next.next; // n2 -> end
    11. }
    12. // n1 中点
    13. n2 = n1.next; // n2 -> right part first node
    14. n1.next = null; // mid.next -> null
    15. Node n3 = null;
    16. while (n2 != null) { // right part convert
    17. n3 = n2.next; // n3 -> save next node
    18. n2.next = n1; // next of right node convert
    19. n1 = n2; // n1 move
    20. n2 = n3; // n2 move
    21. }
    22. n3 = n1; // n3 -> save last node
    23. n2 = head;// n2 -> left first node
    24. boolean res = true;
    25. while (n1 != null && n2 != null) { // check palindrome
    26. if (n1.value != n2.value) {
    27. res = false;
    28. break;
    29. }
    30. n1 = n1.next; // left to mid
    31. n2 = n2.next; // right to mid
    32. }
    33. n1 = n3.next;
    34. n3.next = null;
    35. while (n1 != null) { // recover list
    36. n2 = n1.next;
    37. n1.next = n3;
    38. n3 = n1;
    39. n1 = n2;
    40. }
    41. return res;
    42. }

    这段代码比传统方式要快很多,下面讲一下具体的流程:

    1. if (head == null || head.next == null):首先检查链表是否为空或只包含一个节点,因为这种情况下链表必然是回文,所以直接返回 true

    2. 初始化两个指针 n1n2 都指向链表的头节点 head。这两个指针将用于查找链表的中间节点。

    3. 进入一个循环,条件是 n2.next != null && n2.next.next != null,循环中 n1 每次移动一步,而 n2 每次移动两步,这样当 n2 到达链表尾部时,n1 恰好指向链表的中间节点(如果链表长度为奇数,则中间节点只有一个;如果链表长度为偶数,则中间节点有两个,这里 n1 指向靠左的那一个)。

    4. n2 移动到 n1 的下一个节点,这是为了将链表分为两部分:左边部分和右边部分。

    5. 断开 n1n2 之间的连接,即将 n1.next 设置为 null,从而分割链表为两个独立的部分。

    6. 接下来是将右边部分(后半部分)的链表反转。使用三个指针 n1n2n3 分别指向当前节点、下一个节点和用于保存下下一个节点。通过循环,不断将当前节点的 next 指针反向指向前一个节点,完成链表的反转。

    7. 在反转完成后,n3 会指向反转后链表的头节点,而 n2 则指向左边部分链表的头节点。同时, n1 指向 n3,表示将 n1 移动到反转链表的头节点位置。

    8. 接下来,使用两个指针 n1n2 同时遍历左边部分和反转后的右边部分,比较它们的值是否相等。如果有任何不相等的情况出现,将 res 设置为 false,表示链表不是回文。

    9. 最后,需要将右边部分的链表再次反转回来,以恢复原始链表的结构。这是通过循环和指针操作实现的。

    10. 返回 res,表示是否判断链表为回文。

     

    假设输入链表为:1 -> 2 -> 3 -> 2 -> 1

    1. 首先找到链表的中间节点,n1 指向节点 3。

    2. 将右边部分反转,得到链表:1 -> 2 -> 3 和 1 -> 2。

    3. 通过比较左右两边部分的值,发现它们是回文的。

    4. 最后将右边部分反转回来,得到原始链表:1 -> 2 -> 3 -> 2 -> 1。

  • 相关阅读:
    Python——— 模块
    写组件的过程中没写过的vue3写法
    消息总线 —— SpringCloud Bus
    线程安全集合类
    新手入门案例学习,基于C# MVC实现汽修管理系统《建议收藏:附完整源码+数据库》
    API_异常,数组_方法_面向对象,220814,,
    Cadence OrCAD Capture 如何在原理图中设置网络的飞线拓扑结构
    Jackson 解析 JSON 详细教程
    Regular Expression
    dubbo.xsd的配置
  • 原文地址:https://blog.csdn.net/qq_23953717/article/details/132837593