【链表】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 };