反转链表和部分反转
反转链表
ListNode* reverseList(ListNode* head) {
if(head==nullptr) {
return head;
}
if(head->next==nullptr){
return head;
}
ListNode* p = head;
ListNode* q = p->next;
ListNode* r = nullptr;
p->next = nullptr;
while(q) {
r = q->next;
q->next = p;
p=q;
q=r;
}
return p;
}
关键点:
1.虽是三个指针,但是逐个元素进行操作
2.使用p和q两个指针配合工作,使得两个节点间的指向反向,同时用r记录剩下的链表
3.q是操作完的最后一个元素,因此要返回它
参考:
https://blog.youkuaiyun.com/feliciafay/article/details/6841115
反转链表(部分反转)
给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。
示例 1:
输入:head = [1,2,3,4,5], left = 2, right = 4
输出:[1,4,3,2,5]
示例 2:
输入:head = [5], left = 1, right = 1
输出:[5]
提示:
链表中节点数目为 n
1 <= n <= 500
-500 <= Node.val <= 500
1 <= left <= right <= n
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-linked-list-ii
思路:利用全部反转的逻辑,作一次封装;
关键点:
1.保存或记录要反转部分的前继和后继node;
2.判断特殊值,如,要反转的部分是从链表头开始的这种情况;
/**
* 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:
ListNode *reverseBetween(ListNode *head, int left, int right)
{
if (!head)
return nullptr;
ListNode *p = nullptr;
ListNode *q = nullptr;
p = head;
if (left < 0 || right < 0 || left > right)
return nullptr;
int list_length = 0;
while (p)
{
p = p->next;
list_length++;
}
if (left > list_length || right > list_length)
return nullptr;
int index = 1;
int length = right - left + 1;
ListNode *temp_tail = nullptr;
//要反转的长度就是链表的长度,那直接全部返转
if (length == list_length)
return reverse(head, length, &temp_tail);
//要反转的长度就是链表的长度为1,那可以不作任何操作
if (left == right)
return head;
p = nullptr;//保存要反转部分的前继
q = head;//保存要反转部分的第一个节点
while (index < left)
{
p = q;
q = q->next;
index++;
}
//保存要反转部分的第一个节点
ListNode *temp_head = reverse(q, length, &temp_tail);
//要反转的部分有可能是从链表头部开始的做个判断即可
if (p)
{
p->next = temp_head;
q->next = temp_tail;
return head;
}
else
{
q->next = temp_tail;
return temp_head;
}
}
/*head:反转部分的第一个节点
length:反转部分的长度
tail:指向要反转部分的最后一个结点的下一个元素(以备后序的拼接 )
返回值:返回反转成功后的链表头
*/
ListNode *reverse(ListNode *head, int length, ListNode **tail)
{
if (!head || length == 0)
return nullptr;
ListNode *p = nullptr;;
ListNode *q = nullptr;;
ListNode *r = nullptr;;
p = head;
q = p->next;
p->next = nullptr;
int index = 1;
while (q)
{
r = q->next;
q->next = p;
p = q;
q = r;
index++;
if (index >= length)
{
break;
}
}
*tail = q;
return p;
}
};