文章目录
- 1.234回文链表
- 1.1.题目
- 1.2.解答
- 1.2.1.数组模拟方法
- 1.2.2.反转后半部分链表法
- 2.143重排链表
- 2.1.题目
- 2.2.解答
- 3.141环形链表
- 3.1.题目
- 3.2.解答
1.234回文链表
参考:代码随想录,234回文链表;力扣题目链接
1.1.题目
1.2.解答
1.2.1.数组模拟方法
最直接的想法,就是把链表装成数组,然后再判断是否回文。
使用数组判断回文的时候,使用双指针法,分别从前往后、从后往前遍历,判断数字是否相等即可。
1.2.2.反转后半部分链表法
分为如下几步:
- 用快慢指针,他们都从头节点出发,快指针走两步,慢指针走一步,快指针遇到终止位置时,慢指针就在链表中间位置
注意:
(1)如果有奇数个节点,最后快指针到达链表最后一个节点,慢指针到达中间节点。比如有5个节点1 2 3 4 5
,跳两次,最后快指针到达节点5,慢指针到达节点3。然后划分链表前半部分有2个节点1 2
,后半部分有3个节点3 4 5
。
(2)如果有偶数个节点,最后快指针到达最后一个节点的下一个nullptr
指针,慢指针到达中间节点。比如有4个节点1 2 3 4
,跳两次,最后快指针到达4的下一个位置nullptr
,慢指针到达节点3。然后划分链表前半部分有两个节点1 2
,后半部分有2个节点3 4
。 - 同时用pre记录慢指针指向节点的前一个节点,用来分割链表,pre表示前半部分链表的结尾节点
- 将链表分为前后均等两部分,如果链表长度是奇数,那么后半部分多一个节点
- 将后半部分反转 ,得cur2,前半部分为cur1
- 按照cur1的长度,一次比较cur1和cur2的节点数值
如图所示:
最后给出代码如下:
bool isPalindrome(ListNode *head)
{
if(head == nullptr || head->next == nullptr)
return true;
// 1.寻找分割链表的位置
ListNode* fast = head;
ListNode* slow = head;
ListNode* pre = head;
while(fast && fast->next)
{
pre = slow; // 先备份pre节点
slow = slow->next; // slow走一步
fast = fast->next->next; // fast走两步
}
// 2.此时slow为后半部分链表的head, pre为前半部分链表的结尾
pre->next = nullptr; // 把前半部分链表切分出来,方便后面while循环遍历
ListNode* list1 = head; // 前半部分链表顺序保持不变
ListNode* list2 = reverseList(slow); // 翻转后半部分链表
// 3.以前半部分链表长度为基准,判断前后链表是否相等
while(list1 != nullptr)
{
if(list1->val != list2->val)
return false;
list1 = list1->next;
list2 = list2->next;
}
// 运行到这里说明前后链表相等,因此原链表就是回文链表
return true;
}
// 翻转链表
ListNode* reverseList(ListNode* head)
{
ListNode* pre = nullptr;
ListNode* cur = head;
while(cur != nullptr)
{
ListNode* tmp = cur->next;
cur->next = pre;
pre = cur;
cur = tmp;
}
return pre;
}
2.143重排链表
参考:代码随想录,143重排链表;力扣题目链接
2.1.题目
2.2.解答
3.141环形链表
参考:代码随想录,141环形链表;力扣题目链接