题目描述
给定一个单链表,判断它是否是回文链表,即正着遍历和反着遍历得到的序列相同。
进一步: 能否只使用 $O(n)$ 的时间和额外 $O(1)$ 的空间?
样例1
输入:1->2
输出:false
样例2
输入:1->2->2->1
输出:true
算法
(链表操作) $O(n)$
我们先将链表的后半段翻转,然后用两个指针分别从链表首尾开始往中间扫描,依次判断对应节点的值是否相等,如果都相等,说明是回文链表,否则不是。
链表翻转参见 LeetCode 206. Reverse Linked List 中的 算法1——迭代翻转算法。
空间复杂度分析:链表的迭代翻转算法仅使用额外 $O(1)$ 的空间,所以本题也仅使用额外 $O(1)$ 的空间。
时间复杂度分析:整个链表总共被遍历4次,所以时间复杂度是 $O(n)$。
C++ 代码
/**
* 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) {
int n = 0;
for (ListNode *p = head; p; p = p->next) n ++ ;
if (n <= 1) return true;
ListNode *a = head;
for (int i = 0; i < (n + 1) / 2 - 1; i ++ ) a = a->next;
ListNode *b = a->next;
while (b)
{
ListNode *c = b->next;
b->next = a;
a = b;
b = c;
}
b = head;
ListNode *tail = a;
bool res = true;
for (int i = 0; i < n / 2; i ++ )
{
if (a->val != b->val)
{
res = false;
break;
}
a = a->next;
b = b->next;
}
a = tail, b = a->next;
for (int i = 0; i < n / 2; i ++ )
{
ListNode *c = b->next;
b->next = a;
a = b;
b = c;
}
tail->next = 0;
return res;
}
};
# 思路
# 代码
### 运用栈来判断是否为回文链表
解题思路:
1. 首先统计链表元素的总个数
cnt
,然后可通过元素的总个数求得链表的中点位置x = cnt / 2
;2. 定义
cur = head
,然后移动cur
,将链表前半部分的x
个元素依次入栈,最终cur
指针指向第x
元素的下一个元素;3. 如果
cnt
为奇数,则要跳过当前cur
指向的元素进行下一步判断;4. 比较当前的
cur
指向的元素值是否等于栈顶元素:- 若相等,则将栈顶元素删除,
cur
移动到下一个位置;- 若不相等,则说明链表不是回文链表;
5. 最后判断链表是否为空:若为空,则为回文链表;反之,则不是。
也是很巧妙的
这两行可以不用
我觉得可以使用快慢指针+链表反转 可以少遍历一次
/
* 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:
stack [HTML_REMOVED] s;
vector[HTML_REMOVED] res;
bool isPalindrome(ListNode head) {
ListNode *p = head;
while(p){
res.push_back(p->val);
s.push(p->val);
p = p->next;
}
for(int i = 0;i < res.size();i++){
if(res[i] == s.top()){
s.pop();
}else return false;
}
return true;
}
};
/*
* 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) {
}
有好心人帮忙看看java算法,为什么不能通过[1, 1, 2, 1]测试吗?具体问题出在哪,虽然这个做法确实空间复杂度为O(n)了
https://www.acwing.com/solution/content/23022/ 第一次题解 多多支持
链表奇偶不同的关系,i < (n + 1) / 2 - 1 和下面的i < n / 2怎么考虑的
代特殊值。