目录
- 1、题目
- 2、思路
- 3、c++代码
- 4、java代码
1、题目
请判断一个链表是否为回文链表。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
进阶:
你能否用 时间复杂度和 空间复杂度解决此题?
2、思路
(链表操作)
假设初始的链表是 。

分两步处理:
- 找到链表的中点节点,将其后半段的指针都反向,变成:;
精选力扣500题 第40题 LeetCode 234. 回文链表【c++/java详细题解】 - 然后用两个指针分别从链表首尾开始往中间扫描,依次判断对应节点的值是否相等,如果都相等,说明是回文链表,否则不是。
精选力扣500题 第40题 LeetCode 234. 回文链表【c++/java详细题解】 - 最后再将整个链表复原。
注意点:
- 1、我们选取链表的中点节点为 下取整,是链表的节点个数。
- 2、如果一个链表是奇数个节点(假设为5个节点),将其后半段翻转完后的链表为:
- 3、如果一个链表是偶数个节点(假设为4个节点),将其后半段翻转完后的链表为:
- 4、上图说明连接左右链表节点之间的指向是双向的,具体实现细节看代码
空间复杂度分析: 链表的迭代翻转算法仅使用额外 的空间,所以本题也仅使用额外 的空间。
3、c++代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
bool isPalindrome(ListNode* head) {
int n = 0 ; //统计节点的个数
for(ListNode *p = head ; p ; p = p->next) n++;
if(n <= 1) return true; //节点数<=1的一定是回文链表
//找到中点节点,由第一个节点跳(n+1)/2 -1步到达中点节点
ListNode* a = head;
for(int i = 0; i < (n+1)/2 - 1; i++) a = a->next; //a指针指向链表中点
ListNode* b = a->next; //b指针指向链表中点的下一个节点
while(b) //将链表的后半段反向
{
ListNode* next = b->next; //保留b的next节点
b->next = a;
a = b, b = next;
}
//此时a指向链表的尾节点,我们让b指向链表的头节点
b = head;
ListNode* tail = a; //保留一下尾节点
bool res = true;
for(int i = 0; i < n/2; i++) //判断是否是回文链表
{
if(b->val != a->val)
{
res = false;
break;
}
b = b->next;
a = a->next;
}
//将链表复原,后半段链表翻转
//a指向尾节点,b指向a的下一个节点
a = tail, b = a->next;
for(int i = 0; i < n/2; i++)
{
ListNode* next = b->next;
b->next = a;
a = b , b = next;
}
tail->next = 0;
return res;
}
};
4、java代码
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public boolean isPalindrome(ListNode head) {
int n = 0 ; //统计节点的个数
for(ListNode p = head ; p!=null ; p = p.next) n++;
if(n <= 1) return true; //节点数<=1的一定是回文链表
//找到中点节点,由第一个节点跳(n+1)/2 -1步到达中点节点
ListNode a = head;
for(int i = 0; i < (n+1)/2 - 1; i++) a = a.next; //a指针指向链表中点
ListNode b = a.next; //b指针指向链表中点的下一个节点
while(b!=null) //将链表的后半段反向
{
ListNode next = b.next; //保留b的next节点
b.next = a;
a = b;
b = next;
}
//此时a指向链表的尾节点,我们让b指向链表的头节点
b = head;
ListNode tail = a; //保留一下尾节点
boolean res = true;
for(int i = 0; i < n/2; i++) //判断是否是回文链表
{
if(b.val != a.val)
{
res = false;
break;
}
b = b.next;
a = a.next;
}
//将链表复原,后半段链表翻转
//a指向尾节点,b指向a的下一个节点
a = tail;
b = a.next;
for(int i = 0; i < n/2; i++)
{
ListNode next = b.next;
b.next = a;
a = b ;
b = next;
}
tail.next = null;
return res;
}
}