精选力扣500题 第40题 LeetCode 234. 回文链表c++/java详细题解
Posted 林深时不见鹿
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了精选力扣500题 第40题 LeetCode 234. 回文链表c++/java详细题解相关的知识,希望对你有一定的参考价值。
1、题目
请判断一个链表是否为回文链表。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
进阶:
你能否用
O
(
n
)
O(n)
O(n) 时间复杂度和
O
(
1
)
O(1)
O(1) 空间复杂度解决此题?
2、思路
(链表操作) O ( n ) O(n) O(n)
假设初始的链表是
L
1
→
L
2
→
L
3
→
…
→
L
n
L1→L2→L3→…→Ln
L1→L2→L3→…→Ln。
分两步处理:
-
找到链表的中点节点,将其后半段的指针都反向,变成: L 1 → L 2 → L 3 → … → L ⌈ n / 2 ⌉ ← L ⌈ n / 2 ⌉ + 1 ← … ← L n L1→L2→L3→…→L⌈n/2⌉←L⌈n/2⌉+1←…←Ln L1→L2→L3→…→L⌈n/2⌉←L⌈n/2⌉+1←…←Ln;
-
然后用两个指针分别从链表首尾开始往中间扫描,依次判断对应节点的值是否相等,如果都相等,说明是回文链表,否则不是。
-
最后再将整个链表复原。
注意点:
-
1、我们选取链表的中点节点为 ( n + 1 ) / 2 (n+1)/2 (n+1)/2 下取整, n n n是链表的节点个数。
-
2、如果一个链表是奇数个节点(假设为5个节点),将其后半段翻转完后的链表为:
- 3、如果一个链表是偶数个节点(假设为4个节点),将其后半段翻转完后的链表为:
- 4、上图说明连接左右链表节点之间的指向是双向的,具体实现细节看代码
空间复杂度分析: 链表的迭代翻转算法仅使用额外 O ( 1 ) O(1) O(1) 的空间,所以本题也仅使用额外 O ( 1 ) O(1) O(1) 的空间。
时间复杂度分析: 整个链表总共被遍历4
次,所以时间复杂度是
O
(
n
)
O(n)
O(n)。
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;
}
}
原题链接:234. 回文链表
以上是关于精选力扣500题 第40题 LeetCode 234. 回文链表c++/java详细题解的主要内容,如果未能解决你的问题,请参考以下文章
精选力扣500题 第18题 LeetCode 23. 合并K个升序链表c++详细题解
精选力扣500题 第50题 LeetCode 543. 二叉树的直径c++详细题解
精选力扣500题 第19题 LeetCode 199. 二叉树的右视图c++详细题解
精选力扣500题 第20题 LeetCode 704. 二分查找c++详细题解