1、反转链表
反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode *p1 = 0;
ListNode *p2 = head;
ListNode *pt;
while(p2)
{
pt = p2->next;
p2->next = p1;
p1 = p2;
p2 = pt;
}
return p1;
}
};
/* 递归思想
每次取一个节点放在头部,递归该操作
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(head==0) return 0;
ListNode *p1 = head;
ListNode *p2 = p1->next;
ListNode *pt;
while(p2)
{
pt = p2->next;
p2->next = head;
head = p2;
p1->next = pt;
p2 = pt;
}
return head;
}
};
*/
2、反转 [m, n] 的链表
反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
说明:
1 ≤ m ≤ n ≤ 链表长度。
示例:
输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
ListNode* reverseBetween(ListNode* head, int m, int n) {
if (m == n) return head;
//添加头节点
struct ListNode *newhead = new struct ListNode(0); //头节点
newhead->next = head;
//找到第 m-1 个节点(前段链表尾)、第 m 个节点(中间段链表尾)
ListNode *pre = newhead; //第 m-1 个节点
for (int i = 1; i < m; i++)
{
pre = pre->next;
}
ListNode *pm = pre->next; //第 m 个
//反转链表,次数 n-m 次,最终中间段链表头为 p1, 后段链表头为 p2
ListNode *p1 = pre->next; //第 m 个
ListNode *p2 = p1->next; //第 m+1 个
ListNode *pt;
for (int i = m; i < n; i++)
{
pt = p2->next;
p2->next = p1;
p1 = p2;
p2 = pt;
}
ListNode *pn = p1; //第 n 个
ListNode *after = p2; //第 n+1 个节点
//串起三段链表
pre->next = pn;
pm->next = after;
//去掉头节点
head = newhead->next;
delete newhead;
return head;
}
3、K个一组翻转链表
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
示例 :
给定这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
ListNode* reverseKGroup(ListNode* head, int k) {
if (head == 0) return head;
if (k <= 1) return head;
//添加头节点
ListNode *newhead = new ListNode(0);
newhead->next = head;
//统计链表长度
int cnt = 0;
while (head)
{
cnt++;
head = head->next;
}
//每k个反转一次
head = newhead; //前一个元素
for (int i = 0; i < cnt / k; i++)
{
head = reverseK(head, k); //返回该段最后一个元素
}
//去掉头节点
head = newhead->next;
delete newhead;
return head;
}
ListNode* reverseK(ListNode* head, int k) {
ListNode *pend = head->next; //保留第二段最终的段尾
ListNode *p1 = head->next; //第一个,最终为第二段的段头
ListNode *p2 = p1->next; //第二个,最终为第三段的段头
ListNode *pt;
for (int i = 1; i < k; i++) //k-1次反转
{
pt = p2->next;
p2->next = p1;
p1 = p2;
p2 = pt;
}
head->next->next = p2; //第二段段尾接第三段段头
head->next = p1; //第一段段尾接第二段段头
return pend; //返回第二段最终的段尾
}