zoukankan      html  css  js  c++  java
  • LeetCode 234——回文链表

    1. 题目

    请判断一个链表是否为回文链表。

    示例 1:
    输入: 1->2
    输出: false
    示例 2:

    输入: 1->2->2->1
    输出: true

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

    2. 思路

    定义快慢两个指针,寻找中间结点,同时在慢指针移动的过程中反转前半部分子链表。当找到中间结点时,再分别向前向后比较前后两个子链表的每一个结点值是否相同。

    • 偶数结点情况如下
      3.png

    4.png

    5.png

    6.png

    • 此时,我们分别得到了以 slow 为头指针的前半部分子链表和以 p2 为头指针的后半部分子链表。由于中间结点偏向后边,所以我们需要先比较最中间的两个结点(此处为 2 和 3 结点),然后再依次向两边循环比较直到到达子链的链尾。

    • 再来看奇数结点的情况

    7.png

    8.png

    • 奇数个结点时,我们依然可以分别得到以 slow 为头指针的前半部分子链表和以 p2 为头指针的后半部分子链表。此时,由于 slow 指向的中间结点无须比较,我们只需从 slow 后面第一个结点和 p2 指向的结点开始循环向两边比较即可(此处为 2 和 4 结点)
    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        bool isPalindrome(ListNode* head) {
            
            if (head == NULL || head->next == NULL)     // 空链或只有一个结点,返回 true
            {
                return true;            
            }
            
            else
            {
                /* 此为反转链表的三个指针,slow 即代表 p1 */
                ListNode* slow = head;           // 慢指针指向第一个结点
                ListNode * p2 = slow->next;      // 第二个结点
                ListNode * p3 = p2->next;        // 第三个结点
                
                ListNode* fast = head;           // 快指针指向头结点
    
                // 奇数结点快指针指向最后一个结点结束
                // 偶数结点快指针指向 NULL 结束
                while(fast && fast->next)   
                {
                    p3 = p2->next;
                    fast = fast->next->next;    // 快指针前进两步
                    p2->next = slow;            // 反转链表
                    slow = p2;                  // 慢指针前进一步
                    p2 = p3;
                }
    
                head->next = NULL; // 处理前半部分子链的尾节点
    
                // 偶数结点
                if(!fast)
                {
                    // 先比较 slow 后的两个结点是否相同
                    if (slow->val == slow->next->val)
                    {
                        // 以 slow 后的第三个结点和 p2 指向的结点开始循环向两边比较
                        slow = slow->next->next;
                        while(slow)
                        {
                            if (slow->val != p2->val)
                            {
                                return false;
                            }
                            else
                            {
                                slow = slow->next;
                                p2 = p2->next;
                            }
                        }
                        return true;
                    }
                    else
                    {
                        return false;
                    }
                }
                // 奇数结点
                else
                {
                    // 以 slow 后的第一个结点和 p2 指向的结点开始循环向两边比较
                    slow = slow->next;
                    while(slow)
                    {
                        if (slow->val != p2->val)
                        {
                            return false;
                        }
                        else
                        {
                            slow = slow->next;
                            p2 = p2->next;
                        }
                    }
                    return true;
                }
            }
                    
        }
    };
    

    获取更多精彩,请关注「seniusen」!
    seniusen

  • 相关阅读:
    PAT (Advanced Level) Practice 1071 Speech Patterns (25分)
    PAT (Advanced Level) Practice 1070 Mooncake (25分)
    PAT (Advanced Level) Practice 1069 The Black Hole of Numbers (20分)
    PAT (Advanced Level) Practice 1074 Reversing Linked List (25分)
    PAT (Advanced Level) Practice 1073 Scientific Notation (20分)
    第一次冲刺个人总结01
    构建之法阅读笔记01
    人月神话阅读笔记01
    四则运算2
    学习进度条(软件工程概论1-8周)
  • 原文地址:https://www.cnblogs.com/seniusen/p/9784343.html
Copyright © 2011-2022 走看看