一、问题描述
请判断一个链表是否为回文链表。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
二、解题思路
将链表分为两段,并且把后面一段进行倒置,然后再比较前后两段是否相同即可。最简单的方法就是先计算链表的长度,然后将前面一半用头插法的办法进行倒置,最后再比较,但是由于需要的是一半这个特殊的位置,所以我们可以考虑快慢指针,何谓快慢指针,其实就是两个指针,一根指针一次移动一个位置,另一个指针一次移动两个位置。快慢指针适合用于有中点相关的场景(有中点或倍数的时候可以考虑快慢指针来解决问题)
三、代码实现
/**
* 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 || !head->next) return true;
ListNode *slow = head, *fast = head;
while (fast && fast->next) //快慢指针法,让slow指向链表中部位置
{
slow = slow->next;
fast = fast->next->next;
}
//退出时,fast为最后一个结点或者null,slow处在中间位置
//与结点数有关,左子链表head~slow-1, 右子链表为slow~end
//右子链表比左子链表长一或者相等)
//例:0~10,slow 5, fast 10; 0~9,slow5,fast null (0表示头结点,slow和fast的起点)
ListNode* right = reverseList(slow);//反转右边链表
ListNode* left = head;
while(left && right)//比较左右子链表是否相等
{
if(left->val == right->val)
{
left = left->next;
right = right->next;
}
else
return false;
}
return true;
}
private:
ListNode* reverseList(ListNode* head) {
//pre永远指向null,相当于一个尾节点
ListNode* pre = NULL;
ListNode* cur = head;
while(cur != NULL){
//next用来保存下一个节点。因为会把当前节点cur拿下来,赋值给pre
ListNode* next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
return pre;
}
};