【链表】234. 回文链表

题目:

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

示例 1:

输入: 1->2
输出: false

示例 2:

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

 

解答:

方法一:将值复制到数组中后用双指针法。

 

方法二:递归。

 

方法三:

可以将链表的后半部分反转(修改链表结构),然后将前半部分和后半部分进行比较。比较完成后我们应该将链表恢复原样。虽然不需要恢复也能够通过测试用例,因为使用该函数的人不希望链表结构被更改。

可以分为以下几个步骤:

  A. 找到前半部分链表的尾结点;

  B. 反转后半部分链表;

  C. 判断是不是回文;

  D. 恢复链表;

  E. 返回结果;  

 

 1 /**
 2  * Definition for singly-linked list.
 3  * struct ListNode {
 4  *     int val;
 5  *     ListNode *next;
 6  *     ListNode(int x) : val(x), next(NULL) {}
 7  * };
 8  */
 9 class Solution {
10 public:
11     // 题目解析:
12     // (1)快慢指针法,快指针走两步,慢指针走一步,找到链表的中点;
13     // (2)然后,翻转后半部分;
14     //  (3) 最后,从头、中点开始判断是否为回文;
15     bool isPalindrome(ListNode* head) {
16         if (NULL == head || NULL == head->next)
17         {
18             return true;
19         }
20 
21         ListNode *fast = head;
22         ListNode *slow = head;
23         ListNode *pre = NULL;
24 
25         // 1. 找到链表的中点, 链表长度奇偶不影响
26         while (fast != NULL && fast->next != NULL)
27         {
28             slow = slow->next;
29             fast = fast->next->next;
30         }
31 
32         // 2. 将slow之后的链表进行断开且反转,最后翻转完成之后pre指向反转链表的头结点
33         while (slow)
34         {
35             ListNode *p = slow->next;
36             slow->next = pre;
37             pre = slow;
38             slow = p;
39         }
40 
41         // 3. 前后链表进行比较,注意若为奇数链表,后半部分比前部分多1个结点,然后我们只比较相同长度的结点值,巧妙地避开这点判断
42         while (head && pre)
43         {
44             if (head->val != pre->val)
45             {
46                 return false;
47             }
48             head = head->next;
49             pre = pre->next;
50         }
51 
52         return true;
53     }
54 };

 

posted @ 2020-05-01 17:36  梦醒潇湘  阅读(110)  评论(0)    收藏  举报