文章内容是自己刷leetcode官方刷题攻略的一些经验与总结。
题目链接详见 leetcode刷题攻略
如果喜欢的话,别忘了点个赞哦 ^ _ ^
一.206反转链表
1.题目描述
2.迭代写法
示意图:
我们需要使用双指针来记录节点的前后关系,初始化 pre 指针为 null,cur 指针指向头节点,在迭代过程中,需要每次记录当前节点的 next 指针节点,方便后续更新,最后 pre 指针指向反转后的链表的头节点。
C++ 代码如下:
/**
* 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* reverseList(ListNode* head) {
//双指针法
ListNode *pre = nullptr, *cur = head;
while(cur) {
ListNode *tem = cur->next;
cur->next = pre;
pre = cur;
cur = tem;
}
return pre;
}
};
3.递归写法
示意图:
我们需要层层递归找到原始链表的尾部,然后在回溯过程中再依次修改每个结点的 next 指向,最后原始链表的尾部就是新链表的头节点。
C++代码如下:
/**
* 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* reverseList(ListNode* head) {
//递归写法
//终止条件
if(head == nullptr || head->next == nullptr) { //处理全为空的情况
return head;
}
//递归传入下一个节点,目的是到达最后一个节点
//newHead一直为5,head分别为4,3,2,1
ListNode *newHead = reverseList(head->next);
// cout << newHead->val << endl;
head->next->next = head;
head->next = nullptr;
return newHead;
}
};
二.92反转链表II
1.题目描述
2.题目分析与解答
这里使用一趟扫描的方法,示意图如下:
我用绿色表示的是需要反转的链表,我们可以先使用上一题的方法将这一段链表进行反转,反转后的结果就如图片下方所示。
为了后续链表的连接,我们需要记录图中所示的三个节点,分别是 left 左边第一个节点,right 节点以及 right 右边第一个节点。
我们根据这几个节点进行后续链表的拼接:
得到最终链表。
C++ 代码如下:
/**
* 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) {
//一趟扫描,需要记录left前面一个节点和right后面一个节点
//使用虚拟头节点
ListNode *dummyHead = new ListNode(0, head);
int idx = 1, n = right - left + 1;
ListNode *cur = dummyHead;
//找到left左边位置,用cur记录
while(idx < left) {
cur = cur->next;
idx ++;
}
//实现中间链表翻转
ListNode *cur2 = cur->next;
ListNode *pre = nullptr;
idx = 0;
while(idx < n) {
ListNode *tem = cur2->next;
cur2->next = pre;
pre = cur2;
cur2 = tem;
idx ++;
}
//此时pre指向了right的位置
cur->next->next = cur2;
cur->next = pre;
cur = dummyHead->next;
delete(dummyHead);
return cur;
//
}
};
三.25K个一组翻转链表
1.题目描述
2.题目分析与解答
这道题目我们需要每次反转特定数目的节点,然后分组进行翻转即可,每次反转完一组,要进行节点更新,方便下一次反转。最后如果有剩余,保持原顺序。
使用虚拟头节点处理开头。
第一组反转后结果如下:
进行节点更新:
ListNode *tem = pre;
cur->next->next = cur2;
pre = cur->next;
cur->next = tem;
cur = pre;
C++ 代码如下:
/**
* 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* reverseKGroup(ListNode* head, int k) {
//统计一下链表的长度
int n = 0;
ListNode *cur = head;
while(cur) {
cur = cur->next;
n ++;
}
//统计要进行几次k个数的交换,最后剩下的节点不用逆序
int x = n / k;
//使用虚拟头节点进行操作
ListNode *dummyHead = new ListNode(0, head);
cur = dummyHead;
int idx = 0; //交换次数下标的索引
int idx2 = 0; //每一组k个节点逆序的索引
ListNode *pre = nullptr;
ListNode *cur2 = head;
while(idx ++ < x) {
// pre = nullptr;
idx2 = 0;
while(idx2 ++ < k) {
ListNode *tem = cur2->next;
cur2->next = pre;
pre = cur2;
cur2 = tem;
}
//处理节点赋值,方便下一次循环
ListNode *tem = pre;
cur->next->next = cur2;
pre = cur->next;
cur->next = tem;
cur = pre;
}
cur = dummyHead->next;
delete(dummyHead);
return cur;
}
};