1.题目描述

请判断一个链表是否为回文链表。

示例 1:

输入: 1->2
输出: false

示例 2:

输入: 1->2->2->1
输出: true

进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?

2.解法一:(空间复杂度O(n))

遍历一遍链表压栈,借助栈把链表倒序,然后依次比较“原链表元素”和“新栈中元素”,如果都相等则返回true,否则返回false。

这样简单粗暴,代码的主体包含在解法二中了,这里不列出了。

另外,这种解法的时间要求能不能通过Leetcode的测试,我没有试过,因为觉得没必要试。

3.解法二:(空间复杂度O(n/2))

解题思路:使用两个指针,fast和slow指针。

(1)fast指针每次走两步slow指针每次走一步

(2)fast指针走到链表末尾的时候,slow指针走到链表的中间位置结点(链表长度n为偶数)或中间位置的前一个结点(链表长度n为奇数);

(1)——>(2)——>(3)——>(2)——>(1)
slow fast
(1)——>(2)——>(3)——>(3)——>(2) ——> (1)
slow (fast) 多走1步 fast

  

(3)slow直接到了中间,就可以将整个链表的后半部分压栈实现逆序,依次和前半部分比较,思路同解法一。

注:就是在这里,额外的时间复杂度减少了n/2,因为只需要将链表中一半的元素压栈。

其他的细节,代码里有详细注释。

/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/ static const auto __ = []() {
// turn off sync
std::ios::sync_with_stdio(false);
// untie in/out streams
std::cin.tie(nullptr);
return nullptr;
}(); class Solution {
public:
bool isPalindrome(ListNode* head) {
//额外空间复杂度O(n/2) /*使用两个指针,fast指针每次走两步,slow指针每次走一步;fast指针走到链表末尾的时候,
slow指针走到链表的中间位置结点(链表长度n为偶数)或中间位置的前一个结点(链表长度n为奇数)
*/ //判空
if(head == NULL) return true;
//单节点链表
if(head->next == NULL) return true; ListNode* fast = head;
ListNode* slow = head;//指向第一个结点 //fast指针指向末尾结点,slow指针指向中间位置结点或中间位置的前一个结点 ////注意:这里的结束判断主要看fast!!!
while(fast->next != NULL && fast->next->next != NULL )
{
fast = fast->next->next;
slow = slow->next;
}
//链表长度为偶数,fast指针最后多走一步到链表末尾
if(fast->next)
fast = fast->next; stack<int> s;
//将链表后半部分元素压栈,通过栈来实现逆序
while(slow->next)
{
s.push(slow->next->val);
slow = slow->next;
} //依次比较前半部分元素和逆序的后半部分元素
while(!s.empty())
{
if(s.top() != head->val)
return false;
//前、后一起往后移动
s.pop();
head = head->next;
}
return true;
}
};

4.解法三:(进阶:空间复杂度O(1))

 解题思路:解法三和解法二的区别在于,最后不使用栈来倒序链表后半部分的元素,而是选择直接本地操作(额外空间复杂度为O(1)),在原链表上将后半部分元素倒置(反转),比较完后得出结果后,再 还原链表,返回结果。

代码中有详细注释。

/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/ static const auto __ = []() {
// turn off sync
std::ios::sync_with_stdio(false);
// untie in/out streams
std::cin.tie(nullptr);
return nullptr;
}(); class Solution {
public:
bool isPalindrome(ListNode* head) {
//额外空间复杂度O(1) //判空
if(head == NULL) return true;
//单节点链表
if(head->next == NULL) return true;
//双节点链表
if(head->next->next == NULL)
if(head->val == head->next->val)
return true;
else
return false; ListNode* fast = head;
ListNode* slow = head;//指向第一个结点 //fast指针指向末尾结点,slow指针指向中间位置结点或中间位置的前一个结点 ////注意:这里的结束判断主要看fast!!!
while(fast->next != NULL && fast->next->next != NULL )
{
fast = fast->next->next;
slow = slow->next;
}
//链表长度为偶数,fast指针最后多走一步到链表末尾
if(fast->next)
fast = fast->next; //-----区别在这里,元素不压栈,直接将链表后半部分元素逆序,比较完后得出结果后,再还原链表,返回结果--------// //---------------链表的后半部分元素“倒序”-------------------//
ListNode* p = slow->next;
ListNode* q = NULL;
ListNode* cur = NULL; slow->next = NULL;
while(p)
{
cur = p->next;
p->next = q;
q = p;
p = cur;
} //依次比较 前半部分元素 和 逆序的后半部分元素
while()
{
if(fast->val != head->val)
{
//链表复原
ListNode* m = q->next;
ListNode* n = NULL;
ListNode* cur2 = NULL;
q->next = NULL;
while(m){
cur2 = m->next;
m->next = n;
n = m;
m = cur2;
}
slow->next = n; return false;
} //前、后一起往后移动
fast = fast->next;
head = head->next;

//--------在这里判断结束,是调试的结果----//
//针对这种情况:(3)——>(1)——>(2)——>(3),后半部分反转之后的链表是(3)——>(1)——>(3)——>(2)
// 如果使用while(head->next)作为结束,会少比较一次,也就是最后(1)和(2)不会比较到,从而出错
if(fast == NULL)
break
;
} //链表复原
ListNode* m = q->next;
ListNode* n = NULL;
ListNode* cur2 = NULL;
q->next = NULL;
while(m){
cur2 = m->next;
m->next = n;
n = m;
m = cur2;
}
slow->next = n; return true;
}
};

参考资料:

1.https://blog.csdn.net/blioo/article/details/62050967 单向链表反转(倒置)问题

Leetcode 234. 回文链表(进阶)的更多相关文章

  1. Java实现 LeetCode 234 回文链表

    234. 回文链表 请判断一个链表是否为回文链表. 示例 1: 输入: 1->2 输出: false 示例 2: 输入: 1->2->2->1 输出: true 进阶: 你能否 ...

  2. LeetCode 234——回文链表

    1. 题目 请判断一个链表是否为回文链表. 示例 1: 输入: 1->2 输出: false 示例 2: 输入: 1->2->2->1 输出: true 进阶: 你能否用 O( ...

  3. [LeetCode] 234. 回文链表 ☆(翻转链表)

    描述 请判断一个链表是否为回文链表. 示例 1: 输入: 1->2输出: false示例 2: 输入: 1->2->2->1输出: true 进阶:你能否用 O(n) 时间复杂 ...

  4. leetcode 234 回文链表 Palindrome Linked List

    要求用O(n)时间,和O(1)空间,因此思路是用本身链表进行判断,既然考虑回文,本方法思想是先遍历一次求链表长度,然后翻转前半部分链表:然后同时对前半部分链表和后半部分链表遍历,来判断对应节点的值是否 ...

  5. LeetCode 234. 回文链表

    class Solution { public: bool isPalindrome(ListNode* head) { deque<int> d1, d2; ListNode* p = ...

  6. Leetcode:234 回文链表

    leetcode:234 回文链表 关键点:请判断一个链表是否为回文链表.示例 1:输入: 1->2输出: false示例 2:输入: 1->2->2->1输出: true. ...

  7. leetcode题目234.回文链表(快慢指针+辅助空间-简单)

    题目描述: 请判断一个链表是否为回文链表. 示例 1: 输入: 1->2 输出: false 示例 2: 输入: 1->2->2->1 输出: true 进阶: 你能否用 O( ...

  8. 领扣(LeetCode)回文链表 个人题解

    请判断一个链表是否为回文链表. 示例 1: 输入: 1->2 输出: false 示例 2: 输入: 1->2->2->1 输出: true 进阶:你能否用 O(n) 时间复杂 ...

  9. [LeetCode题解]234. 回文链表 | 快慢指针 + 反转链表

    解题思路 找到后半部分链表,再反转.然后与前半部分链表比较 代码 /** * Definition for singly-linked list. * public class ListNode { ...

随机推荐

  1. kubernetes相关

    1.获取client , api-server 加token 或in-cluster方式 2.所有对象均有list update get 等方法 3.对象属性源码追踪,yaml与源码一一对应 4.一些 ...

  2. Elasticsearch 评分score计算中的Boost 和 queryNorm

    本来没有这篇文章,在公司分享ES的时候遇到一个问题,使用boost的时候,怎么从评分score中知道boost的影响. 虽然我们从查询结果可以直观看到,boost起了应有的作用,但是在explain的 ...

  3. python3中使用python2中cmp函数出现错误

    在python2中我们经常会使用cmp函数来比较一些东西,但是在python3中,你再来使用这个函数的时候,发现就报错了,提示找不到这个函数,这是为啥呢? 答:新版的python已经舍弃这种用法 而在 ...

  4. 《Linux编程大作业》

    一.要求 作业题目 Linux下的多进程/线程网络通信 作业目标 要求学生熟练掌握<Linux编程>课程中的知识点,包括Linux常用命令.bash脚本.编译和调试环境.读写文件.进程间通 ...

  5. 软件工程第四周作业之四则运算-C#实现

    拿到题目的时候,快放假了,也没心思做.十月七号的一下午大概从两点做到八点半,加上十月八号的十二点半到两点半,做了一共八个半小时,去掉吃饭半个小时那么一共做了八个小时. 逆波兰表达式我是扒的别人代码,没 ...

  6. C语言 命令行参数 函数指针 gdb调试

    . 作者 : 万境绝尘 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/21551397 | http://www.hanshul ...

  7. 3dContactPointAnnotationTool开发日志(一)

      周日毕设开题报告结束后浪了一天,今天又要开始回归正轨了.毕设要做一个人和物体的接触点标注工具,听上去好像没啥难度,其实实现起来还是挺麻烦的.   今天没做啥,就弄了个3d场景做样例.把界面搭了一下 ...

  8. lol人物模型提取(五)

      修改了发过去后,那边说吊坠的绳子太细了,厚度至少1mm,推荐是2mm,需要我自己加粗,没办法又得用3ds max一根一根线地缩放了.   修改好后问报价,高精度树脂打印需要730元,还不带上色的, ...

  9. Android 如何判断CPU是32位还是64位

    转自:http://blog.csdn.net/wangbaochu/article/details/47723265 1. 读取Android 的system property ("ro. ...

  10. DEDE去掉会员登录及注册验证码的方法

    1.登录打开member/index_do.php 删除245-250行,即: if(strtolower($vdcode)!=$svali || $svali=='') { ResetVdValue ...