「leetcode」234. 回文链表:【数组模拟】【翻转后半部分】详解
程序员文章站
2022-07-15 16:11:05
...
本文 https://github.com/youngyangyang04/leetcode-master 已经收录,里面还有leetcode刷题攻略、各个类型经典题目刷题顺序、思维导图,可以fork到自己仓库,有空看一看一定会有所收获,如果对你有帮助也给一个star支持一下吧!
题目链接
https://leetcode-cn.com/problems/palindrome-linked-list/
思路
数组模拟
最直接的想法,就是把链表装成数组,然后再判断是否回文。
代码也比较简单。如下:
class Solution {
public:
bool isPalindrome(ListNode* head) {
vector<int> vec;
ListNode* cur = head;
while (cur) {
vec.push_back(cur->val);
cur = cur->next;
}
// 比较数组回文
for (int i = 0, j = vec.size() - 1; i < j; i++, j--) {
if (vec[i] != vec[j]) return false;
}
return true;
}
};
上面代码可以在优化,就是先求出链表长度,然后给定vector的初始长度,这样避免vector每次添加节点重新开辟空间
class Solution {
public:
bool isPalindrome(ListNode* head) {
ListNode* cur = head;
int length = 0;
while (cur) {
length++;
cur = cur->next;
}
vector<int> vec(length, 0); // 给定vector的初始长度,这样避免vector每次添加节点重新开辟空间
cur = head;
int index = 0;
while (cur) {
vec[index++] = cur->val;
cur = cur->next;
}
// 比较数组回文
for (int i = 0, j = vec.size() - 1; i < j; i++, j--) {
if (vec[i] != vec[j]) return false;
}
return true;
}
};
反转后半部分链表
分为如下几步:
- 用快慢指针,快指针有两步,慢指针走一步,快指针遇到终止位置时,慢指针就在链表中间位置
- 同时用pre记录慢指针指向节点的前一个节点,用来分割链表
- 将链表分为前后均等两部分,如果链表长度是奇数,那么后半部分多一个节点
- 将后半部分反转 ,得cur2,前半部分为cur1
- 按照cur1的长度,一次比较cur1和cur2的节点数值
如图所示:
代码如下:
class Solution {
public:
bool isPalindrome(ListNode* head) {
if (head == nullptr || head->next == nullptr) return true;
ListNode* slow = head; // 慢指针,找到链表中间分位置,作为分割
ListNode* fast = head;
ListNode* pre = head; // 记录慢指针的前一个节点,用来分割链表
while (fast && fast->next) {
pre = slow;
slow = slow->next;
fast = fast->next->next;
}
pre->next = nullptr; // 分割列表
ListNode* cur1 = head; // 前半部分
ListNode* cur2 = reverseList(slow); // 反转后半部分,总链表长度如果是奇数,cur2比cur1多一个节点
// 开始两个链表的比较
while (cur1) {
if (cur1->val != cur2->val) return false;
cur1 = cur1->next;
cur2 = cur2->next;
}
return true;
}
// 反转链表
ListNode* reverseList(ListNode* head) {
ListNode* temp; // 保存cur的下一个节点
ListNode* cur = head;
ListNode* pre = nullptr;
while(cur) {
temp = cur->next; // 保存一下 cur的下一个节点,因为接下来要改变cur->next
cur->next = pre; // 翻转操作
// 更新pre 和 cur指针
pre = cur;
cur = temp;
}
return pre;
}
};
我是程序员Carl,利用工作之余重刷leetcode,更多精彩算法文章尽在:代码随想录,关注后,回复「Java」「C++」「python」「简历模板」等等,有我整理多年的学习资料,可以加我微信,备注「简单自我介绍」+「组队刷题」,拉你进入刷题群(无任何广告,纯个人分享),每天一道经典题目分析,我选的每一道题目都不是孤立的,而是由浅入深一脉相承的,如果跟住节奏每篇连续着看,定会融会贯通。
以下资料希望对你有帮助:
- 学习资料以及我的开源项目
- 我的B站视频:算法和编程语言的讲解
- leetcode刷题攻略
- 程序员应该如何写简历(附简历模板)
- 一线互联网公司技术面试的流程以及注意事项
- C++面试&C++学习指南知识点整理
如果感觉题解对你有帮助,不要吝啬给一个????吧!
上一篇: 19. 删除链表的倒数第N个节点【双指针经典应用】详解
下一篇: shiro前后端分离后端部分代码