文章目录
问题:反转整个链表
一、使用栈
利用栈先进后出的特性,遍历链表,将每个结点加入栈中,最后进行出栈操作,先出栈的结点指向临近的后出栈的结点。
C++代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
stack<ListNode*>s;
while(head){//将单链表节点逐个入栈
s.push(head);
head = head->next;
}
ListNode *list = new ListNode(0);//增加一个头节点
ListNode *tail = list;
while(!s.empty()){
tail->next = s.top();
tail = s.top();
s.pop();//出栈
}
tail->next = NULL;//tail是反转后的链表的最后一个节点
return list->next;//返回反转后的链表
}
};
二、使用两个指针
遍历链表,用pre表示前一个结点,cur表示当前结点,遍历一遍即可
C++代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(!head) return NULL;
ListNode *pre = NULL, *cur = head;
while(cur){
ListNode *tmp = cur->next;//记录下一个节点
cur->next = pre; //反转
pre = cur;
cur = tmp;
}
return pre;//返回新的头节点
}
};
三、使用递归的方法
List reverse3(List list)表示将单链表 list 进行反转并返回新链表的头节点,递归考虑,那么reverse3(list->next)的作用就是将list结点之后的链表进行反转,因此我们只需将反转后的链表的最后一个结点(也就是list->next)指向list,并将list指向NULL,即可。
C++代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
//当head为空或者head是最后一个元素时直接返回
if(!head || !head->next) return head;
//递归对head节点之后的链表进行逆转,逆转后的头节点是newhead
ListNode *newhead = reverseList(head->next);
head->next->next = head;
head->next = NULL;
return newhead;
}
};
问题:两两交换链表中的节点
解题思路
采用递归的思路,swapPairs(ListNode* head)函数返回以head为头节点的链表两两交换节点后的新链表的头节点。递归边界:当head是最后一个节点或为NULL,直接返回。
C++代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
if(!head || !head->next) return head;
//递归处理以p2->next为头节点的剩余链表
//用p3指向处理后的链表的头节点
ListNode *p1 = head, *p2=head->next;
ListNode *p3 = swapPairs(p2->next);
p2->next = p1;
p1->next = p3;
return p2;
}
};
问题:K 个一组翻转链表
解题思路
文章开头是反转整个链表,这里是每k个节点进行反转操作,为方便操作新增一个头节点,遍历链表,用begin记录开始遍历的位置,然后向后遍历k-1个节点,进行断开链表操作,然后对这部分调用反转整个链表的函数,并把它链接到反转完成的链表中,重复这个步骤,直到遍历完。
C++代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
if(!head || k < 1) return head;//不用处理
ListNode *list = new ListNode(0);//增加一个头节点
ListNode *tail = list, *begin = head;
int cnt = 0;//计数值
while(head){
cnt++;//当前节点的编号是cnt
if(cnt % k == 0){//要进行反转
ListNode *tmp = head->next;//下一次开始的节点
head->next = NULL;//断开链表
tail->next = reverse(begin);//进行反转操作
//反转后begin变成最后一个节点,更新tail
tail = begin;
begin = tmp;//更新此次开始的节点
head = begin;//让head指向开始节点
}
else{
head = head->next;
}
}
//begin指向最后一段不足k的开始节点或者指向为NULL
tail->next = begin;
return list->next;
}
//将begin到end的之间的链表进行反转
ListNode* reverse(ListNode *head){
//如果head为NULL或者是最后一个节点,直接返回
if(!head || !head->next) return head;
//将head节点之后的链表进行反转
ListNode *newHead = reverse(head->next);
head->next->next = head;
head->next = NULL;
return newHead;//返回头节点
}
};